diff options
author | Joel Sherrill <joel.sherrill@oarcorp.com> | 2015-05-27 14:06:08 -0700 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@oarcorp.com> | 2015-05-27 14:06:08 -0700 |
commit | 0cf3eab3e52e2e661fd70c54d30297e1f008019b (patch) | |
tree | 2bc8e115470552a5a437b90771a12fe73fb77d25 | |
parent | libtecla-1.6.3: Use cross strip program (diff) | |
download | rtems-addon-packages-0cf3eab3e52e2e661fd70c54d30297e1f008019b.tar.bz2 |
libtecla 1.6.1: Remove after update to 1.6.3
148 files changed, 0 insertions, 58190 deletions
diff --git a/libtecla-1.6.1/CHANGES b/libtecla-1.6.1/CHANGES deleted file mode 100644 index b02c224..0000000 --- a/libtecla-1.6.1/CHANGES +++ /dev/null @@ -1,2758 +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. - -31/10/2004 mcs@astro.caltech.edu (problem reported by Godfrey van der Linden) - getline.c - The gl_event_handler() function had the endif of a - conditional compilation clause in the wrong place. This - only upset the compiler on unusual systems that don't - have select(). The problem was seen under Mac OS X, due - to the configuration problem in 1.6.0 that caused the - configure script to mistakenly report that select wasn't - available. - -31/10/2004 mcs@astro.caltech.edu (info provided by Ivan Rayner) - configure.in configure Makefile.in - Ivan reported that under IRIX 6.5 it is necessary to add - -D_XOPEN_SOURCE=500 to the compiler flags, when compiling - the reentrant version of the library. Thus, whereas - previously I hardwired the value of DEFINES_R in - Makefile.in, I have now made this a variable in the - configure script, which is augmented with the above - addition, within an IRIX-specific switch clause. - - Also apparently configure leaves the RANLIB variable - blank, instead of setting it to ":", so I have now - explicitly set this to ":", within the new IRIX clause of - the configure script. - -31/10/2004 mcs@astro.caltech.edu (info provided by Ivan Rayner) - getline.c - Under IRIX, the compiler warned that gl_read_unmasked() - was returning an int, which was then being assigned to an - enumeration type. This is techically fine, but it - highlighted the fact that I had meant to declare - gl_read_unmasked() to directly return the enumerated - type. I have now done so. - -26/09/2004 mcs@astro.caltech.edu - getline.c - Users can now turn off interactive command-line editing - by setting the TERM environment variable to the word "dumb". - -18/07/2004 mcs@astro.caltech.edu (problem noted by Michael MacFaden) - getline.c - Calling gl_terminal_size() on a system without support - for SIGWINCH caused a divide-by-zero error in an unintended - call to gl_erase_line(), because gl_update_size() was - incorrectly being called to query the terminal size, - instead of gl_query_size(). - -18/07/2004 Padraig Brady (documented here by mcs@astro.caltech.edu) - getline.c - The suspend and termination signal-handlers installed by - gl_tty_signals(), were being installed swapped. - -03/06/2004 Mike Meaney (documented here by mcs@astro.caltech.edu) - getline.c - Mike pointed out the fact that the curses setupterm() - function is actually documented to exit the application - if an error occurs while its optional errret argument is - NULL. I hadn't noticed this, and because I didn't need - the extra information returned in the errret argument, I - was passing it a NULL. As suggested by Mike, I now pass - this argument a pointer to a dummy errret variable. - -23/05/2004 mcs@astro.caltech.edu (problem noted by John Beck) - man/func/cpl_complete_word.in - Some of the prototypes of functions and types documented - by the cpl_complete_word man page, weren't listed in the - Synopsis section of this man page. They are now listed - there. - -23/05/2004 mcs@astro.caltech.edu - getline.c man/func/gl_get_line.in - I have now added support for calling gl_normal_io() from - any callback functions that the application installs by - calling either gl_inactivity_timeout(), or gl_watch_fd(). - Previously, if one of these callback functions called - gl_normal_io(), then after returning to gl_get_line(), - gl_get_line() would incorrectly assume that the terminal - was still in raw I/O mode. Now, gl_get_line() checks to - see if gl_normal_io() was called by the callback, and - if so, calls _gl_raw_io() to reinstate raw I/O mode. - -21/05/2004 mcs@astro.caltech.edu - configure.in configure - On Mac OS X the code that the configure script used to - check for select() failed due to missing symbols in - sys/select.h. Moving the inclusion of sys/select.h to - after the inclusion of sys/time.h, sys/types.h and - sys/unistd.h fixed this. - -11/05/2004 mcs@astro.caltech.edu - getline.c man/func/gl_get_line.in - If the line buffer returned by one call to gl_get_line() - was passed as the start_line argument of the next call to - gl_get_line(), then instead of the just-entered line - being presented back to the user for further editing, the - start_line argument was effectively ignored, because the - line buffer whose pointer was being passed back, was - being cleared before the start_line pointer was examined. - This appears to have been a case of me incorrectly - thinking that I had forgotten to initialize gl->line[] - and gl->ntotal in the gl_reset_input_line() function, and - then "fixing" this supposed omission. Removing this - erroneous fix, restored things to how they were meant to - be. To make it unlikely that I will make the same mistake - again, I have renamed the function from - gl_reset_input_line() to gl_reset_editor(), to stop it - looking as though it is meant to reset the contents of - the input line (that is what gl_truncate_buffer() is - for), explicitly stated that it doesn't clear the input - line, in the header comments of the function, and added a - prominent warning comment in the body of the function. - - Also, since support for passing back the returned line - pointer via the start_line argument of the next call to - gl_get_line(), wasn't documented in the man page, but was - meant to be supported, and definitely used to work, I - have now amended the man page documentation of - gl_get_line() to explicitly state that this feature is - officially supported. - -2?/04/2004 Released 1.6.0 - -22/04/2004 mcs@astro.caltech.edu (Fixed a bug reported by John Beck) - getline.c - When an error, signal, or other abnormal event aborted - gl_get_line(), the cleanup code that restored the - terminal to a sane state, also overwrote the value of - errno that was associated with the aborting event. An - I/O error occurring in the cleanup code would have also - overwritten the value to be returned by - gl_return_status(), and thus remove any possibility of - the caller finding out what really caused gl_get_line() - to abort. I have now written a new internal function - called, gl_record_status(), which records the completion - status to be returned by gl_return_status(), and the - value to assign to errno just before gl_get_line() - returns. This is called wherever code detects conditions - that require gl_get_line() to return early. The function - ensures that once an abnormal completion status has been - recorded for return, subsequent completions statuses - aren't recorded. This ensures that the caller sees the - original cause of the abnormal return, rather than any - error that occurs during cleaning up from this before - return. - -17/04/2004 mcs@astro.caltech.edu - getline.c - If an application's callback called gl_read_char() after - calling gl_normal_io(), it would inappropriately - redisplay the input line, when it called _gl_raw_io() to - temporarily switch the terminal back into raw mode. - - To fix this, _gl_raw_io() now takes a new 'redisplay' - argument, which specifies whether or not to queue a - redisplay of the input line. I also created a new - gl->postpone flag, which is set by gl_normal_io(), and - cleared by _gl_raw_io() (when its redisplay argument is - true). When this flag is set, gl_flush_output() ignores - queued redisplays, as it generally should between calls - to gl_normal_io() and gl_raw_io(). Thus its effect is to - postpone redisplays while line editing is suspended. - -11/04/2004 mcs@astro.caltech.edu - history.c man/misc/tecla.in - History searches can now include the globbing operators - *, ?, []. When a search prefix is found to have at least - one of these characters, then only history lines that - completely match that pattern are returned. - -11/04/2004 mcs@astro.caltech.edu (issue raised by Mark Coiley) - getline.c ioutil.c - There appears to be a bug in Solaris's terminal I/O. - When the terminal file descriptor is placed in - non-blocking I/O mode, and the terminal is switched from - canonical to raw mode, characters that were previously - entered in canonical I/O mode don't become available to - be read until the user types one character more. Select() - incorrectly says that there are no characters available, - and read() returns EAGAIN. This is only a problem for - gl_get_line() when gl_get_line() is in non-blocking - server I/O mode, so most users won't have experienced any - problems with this. - - The only way that I have found to get read() to return - the characters, without the user first having to type - another character, is to turn off non-blocking I/O before - calling read(). Select() still claims that there are no - characters available to be read, but read happily returns - them anyway. Fortunately, one can perform non-blocking - terminal reads without setting the non-blocking I/O flag - of the file descriptor, simply by setting the VTIME - terminal attribute to zero (which I already was - doing). Thus, when in non-blocking server I/O, I now turn - off the non-blocking I/O flag, attempt to read one - character and only if this fails, do I then call the - select() based event handler to implement any configured - non-zero timeout, before attempting the read again. Of - course the non-blocking I/O flag is still needed for - writing, so I only turn it off temporarily while reading. - -25/03/2004 mcs@astro.caltech.edu (bug reported by Gregory Harris) - Makefile.in - It appears that when in February, I patched Makefile.in - to add abolute paths to the install-sh shell-script, - I accidentally replaced install-sh with install.sh. I - corrected the name in the Makefile. - -25/03/2004 Gregory Harris (documented here by mcs) - configure.in configure - Greg added the configuration parameters needed to build - the shared version of the libtecla library under FreeBSD. - -25/03/2004 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man/func/gl_get_line.in - man/func/gl_read_char.in - I wrote a public function called gl_read_char(). Unlike - gl_query_char(), this function neither prompts the user - for input, nor displays the character that was entered. - In fact it doesn't write anything to the terminal, and - takes pains not to disturb any incompletely entered - input line, and can safely be called from application - callback functions. - -21/03/2004 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man/func/gl_get_line.in - man/func/gl_query_char.in - I wrote a public function called gl_query_char(), which - prompts the user and awaits a single-character reply, - without the user having to hit return. - -23/02/2004 mcs@astro.caltech.edu (bug reported by Gregory Harris) - configure.in configure getline.c enhance.c demo3.c - The configure script now checks for the sys/select.h - header file, and arranges for a C macro called - HAVE_SYS_SELECT_H to be set if it exists. Thus the files - that use select() now use this macro to conditionally - include sys/select.h where available. Apparently this - header is required under FreeBSD 5.1. - -23/02/2004 mcs@astro.caltech.edu - getline.c libtecla.h man/func/gl_get_line.in - I wrote two new public functions, gl_append_history() and - gl_automatic_history(). Together these allow the - application to take over the responsibility of adding - lines to the history list from gl_get_line(). I then - documented their functionality in the gl_get_line man - page. - Version 1.6.0 - I incremented the minor version number of the library, to - comply with the requirement to do so when additions are - made to the public interface. See libtecla.map for - details. - libtecla.map - I added a new 1.6.0 group for the new minor version, and - added the above pair of functions to it. - -15/02/2004 mcs@astro.caltech.edu (fixes a bug reported by Satya Sahoo) - history.c - Calling gl_load_history() multiple times, eventually led - to a segmentation fault. This was due to the head of the - list of unused history string segments not getting - reset when the history buffer was cleared. While - debugging this problem I also noticed that the history - resizing function was way too complicated to verify, so - after fixing the above bug, I heavily simplified the - history resizing function, trading off a small reduction - in memory efficiency, for greatly improved clarity, and - thus made it much more verifiable and maintainable. - -14/02/2004 mcs@astro.caltech.edu (fixes a bug reported by Tim Burress). - getline.c - If gl_change_terminal() was first used to tell - gl_get_line to read input from a file, then called later - to tell it to read subsequent input from a terminal, no - prompt would be displayed for the first line of - interactive input. The problem was that on reaching the - end of the input file, gl_get_line() should have called - gl_abandon_line(), to tell the next call to gl_get_line() - to start inputting a new line from scratch. I have added - this now. - -14/02/2004 Krister Walfridsson (documented here by mcs@astro.caltech.edu) - Makefile.in - Krister noticed that I had failed to put $(srcdir)/ in front - of some invokations of install.sh. I have remedied this. - config.guess config.sub - I hadn't updated these for a long time, so apparently they - didn't recognise the BSD system that Krister was using. - I have now updated them to the versions that come with - autoconf-2.59. - -22/01/2004 mcs@astro.caltech.edu - keytab.c - When parsing key-binding specifications, backslash escaped - characters following ^ characters were not being expanded. - Thus ^\\ got interpretted as a control-\ character followed - by a \ character, rather than simply as a control-\ - character. - -12/01/2004 mcs@astro.caltech.edu - cplfile.c cplmatch.c demo2.c demo3.c demo.c direader.c - expand.c getline.c history.c homedir.c pathutil.c pcache.c - configure.in configure INSTALL - The configuration script now takes a - "--without-file-system" argument. This is primarily for - intended for embedded systems that either don't have - filesystems, or where the file-system code in libtecla is - unwanted bloat. It sets the WITHOUT_FILE_SYSTEM - macro. This removes all code related to filesystem - access, including the entire public file-expansion, - file-completion and path-lookup facilities. Note that the - general word completion facility is still included, but - without the normally bundled file completion - callback. Actually the callback is still there, but it - reports no completions, regardless of what string you ask - it to complete. - - This option is described in the INSTALL document. - -12/01/2004 mcs@astro.caltech.edu - getline.c configure.in configure INSTALL - The configuration script now takes a - "--without-file-actions" argument. This allows an - application author/installer to prevent users of - gl_get_line() from accessing the filesystem from the - builtin actions of gl_get_line(). It defines a macro - called HIDE_FILE_SYSTEM. This causes the - "expand-filename", "read-from-file", "read-init-files", - and "list-glob" action functions to be completely - removed. It also changes the default behavior of actions - such as "complete-word" and "list-or-eof" to show no - completions, instead of the normal default of showing - filename completions. - - This option is described in the INSTALL document. - -11/01/2004 mcs@astro.caltech.edu - getline.c man/func/gl_get_line.in - In case an application's customized completion handler - needs to write to the terminal for some unforseen reason, - there needs to be a way for the it to cleanly suspend raw - line editing, before writing to the terminal, and the - caller then needs to be aware that it may need to - resurrect the input line when the callback returns. I - have now arranged that the completion callback functions - can call the gl_normal_io() function for this purpose, - and documented this in the gl_get_line() man page. - -11/01/2004 mcs@astro.caltech.edu (In response to a bug report by Satya Sahoo) - getline.c - The gl_configure_getline() function makes a malloc'd copy - of the names of the configuration files that it is asked - to read. Before the bug fix, if the application made one - or more calls to this function, the memory allocated by - the final call that it made before calling del_GetLine(), - wasn't being freed. Note that memory allocated in all but - the final call was being correctly freed, so the maximum - extent of the memory leak was the length of the file - name(s) passed in the final call to - gl_configure_getline(), and an application that didn't - call gl_configure_getline() didn't suffer any leak. - -20/12/2003 mcs@astro.caltech.edu - history.c - Ellen tested the history fix that I reported below, and - pointed out that it still had a problem. This turned out - to be because getline.c was making some incorrect - assumptions about the new behavior of history.c. This - problem and the previous one both revolved around how - search prefixes were stored and discarded, so I have now - re-written this part of the code. Previously the search - prefix was retained by looking for a line with that - prefix, and keeping a pointer to that line. This saved - memory, compared to storing a separate copy of the - prefix, but it led to all kinds of hairy - interdependencies, so I have now changed the code to keep - a separate copy of search prefixes. To keep the memory - requirements constant, the search prefix is stored in the - history buffer, like normal history lines, but not - referenced by the time-ordered history list. The prefix - can now be kept around indefinitely, until a new search - prefix is specified, regardless of changes to the - archived lines in the history buffer. This is actually - necessary to make the vi-mode re-search actions work - correctly. In particular, I no longer discard the search - prefix whenever a history search session ends. Also, - rather than have getline.c keep its own record of when a - history session is in progress, it now consults - history.c, so that failed assumptions can't cause the - kind of discrepancy that occurred before. For this to - work, getline.c now explicitly tells history.c to cancel - search sessions whenever it executes any non-history - action. - -14/12/2003 mcs@astro.caltech.edu (bug reported by Ellen Oschmann) - history.c - If one searched backwards for a prefix, then returned to - the original line, changed that line, then started - another backwards prefix search, getline incorrectly - discarded the new search prefix in the process of - throwing away its cached copy of the previous pre-search - input line. In other words getline was belatedly - cancelling a previous search, after a new search had - already partially begun, and thus messed up the new - search. The obvious fix was to arrange for the current - search to be cancelled whenever the history pointer - returns to its starting point, rather than waiting for - the next search to begin from there. - -14/12/2003 mcs@astro.caltech.edu - history.c - _glh_recall_line() was returning the last line in the - history buffer instead of the line requested by the - caller. This only affected the obscure "repeat-history" - action-function, which probably isn't used by anybody. - -09/12/2003 Version 1.5.0 released. - -28/09/2003 mcs@astro.caltech.edu - homedir.c - When the home directory of the login user is requested, - see if the HOME environment variable exists, and if so - return its value, rather than looking up the user's home - directory in the password file. This seems to be the - convention adopted by other unix programs that perform - tilde expansion, and it works around a strange problem, - where a third-party libtecla program, statically compiled - under an old version of RedHat, unexpectedly complained - that getpwd() returned an error when the program was run - under RedHat 9. - -01/09/2003 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man/func/gl_get_line.in - man/func/gl_register_action.in. - It is now possible for an application to register - external functions as action functions. These actions are - initially bound to specified key-sequences, but if they - are registered before the user's configuration file is - loaded, they can also be re-bound by the user to - different key-sequences. The function used to register a - new action, is called gl_register_action(). Action - functions are passed a readonly copy of the input line - and the cursor position. They can display text to the - terminal, or perform other operations on the application - environment. Currently, they can't edit the input line or - move the cursor. This will require the future addition of - functions to queue the invokation of the built-in action - functions. - -26/08/2003 mcs@astro.caltech.edu - getline.c - I modified gl_update_buffer() to ensure that the cursor - stays within the input line after external line - modifications, and to queue a redisplay of the - potentially modified input line. - -21/07/2003 mcs@astro.caltech.edu - configure.in configure Makefile.in Makefile.stub INSTALL - By specifying --without-man-pages or --with-man-pages=no - as command-line arguments to the configure script, it is - now possible to have the configure script skip the - man-page preprocessing step, and arrange for the man-page - installation targets in the Makefile to do nothing. This - option is designed for people who embed libtecla within - other packages. It is also used by Makefile.stub when - the distclean target is specified. - -21/07/2003 mcs@astro.caltech.edu - configure.in configure - The previous workaround for recent versions of gcc - placing /usr/local/include at the start of the system - inlcude-file search path, broke something else. The fix - placed /usr/include before gcc's include area, which - meant that gcc's modified version of stdarg.h was being - ignored in deference to the version in /usr/include. I - have changed the fix to have gcc report the search path, - then have awk add options to CFLAGS to reorder this path, - plaing /usr/local/include at the end. - - Also, under Solaris 9, including term.h without first - including curses.h results in complaints about undefined - symbols, such as bool. As a result the configure script's - test for term.h was failing. I have now modified it to - include curses.h in the test code that it uses to check - for term.h. In the process I also improved the tests for - curses.h and term.h to prevent an ncurses version of - term.h from being used with the system-default version of - curses.h. - -29/06/2003 mcs@astro.caltech.edu - Makefile.in direader.c homedir.c - On some systems (eg. linux) the _POSIX_C_SOURCE - feature-test macro is set by system headers, rather than - being an option set by a project's Makefile at - compilation time. In software, such as tecla, where the - definition of this macro is used as an indication of - whether to use the non-reentrant or reentrant versions of - system functions, this means that the reentrant functions - are always used, regardless of whether this macro is set - or not by the project Makefile. Thus, on such systems the - reentrant and non-reentrant versions of the tecla library - are essentially identical. This has a couple of - drawbacks. First, since thread-safe functions for - traversing the password file don't exist, the supposedly - non-reentrant version of the tecla library can't support - ambiguous tab-completion of usernames in ~username/ - constructions. Secondly, on some systems the use of - reentrant system functions dictates the use of a shared - library that isn't needed for the non-reentrant - functions, thus making it more difficult to distribute - binary versions of the library. - - To remedy this situation I have modified the DEFINES_R - variable in Makefile.in to arrange for the compiler to - define a C macro called PREFER_REENTRANT when it is - compiling the reentrant version of the tecla library. - This macro is now used in the source code to determine - when to require reentrant code. Whithin the source code, - wherever a potentially non-reentrant interface is used, - the existance of both this macro and a suitably valued - _POSIX_C_SOURCE macro, are tested for to see if a - reentrant alternative to the problem code should be used. - -22/06/2003 mcs@astro.caltech.edu - getline.c - I changed the way that redisplays are requested and - performed. Redisplays are now queued by calling - gl_queue_redisplay(), and subsequently performed by - gl_flush_output(), when the queue of already pending - output has been completely dispatched. This was necessary - to prevent event handlers from filling up the output - queue with redisplays, and it also simplifies a number of - things. In the process I removed the gl_queue_display() - function. I also wrote a gl_line_erased() function, which - is now called by all functions that erase the input - line. I also split the gl_abandon_line() function into - public and private callable parts, and used the private - version internally to arrange to discard the input line - after errors. - - The raw_mode flag was not being initialized by new_GetLine(). - It is now initialized to zero. - - I removed the zapline flag, since using the endline flag to - communicate the desire to terminate the line, did the same - thing. - - gl_terminal_move_cursor() now does nothing when the input - line isn't displayed. - -18/03/2003 mcs@astro.caltech.edu - getline.c - Fixed bug which was causing newlines not to be output - at the end of each newly entered line. I was - interpreting the gl->endline flag in conflicting ways in - two places. To fix this I have created a gl->displayed - flag. This flags whether an input line is currently - displayed. - -17/03/2003 mcs@astro.caltech.edu - getline.c libtecla.h man/func/gl_get_line.in - man/func/gl_erase_terminal.in libtecla.map - I added a new function that programs can call to clear - the terminal between calls to gl_get_line(). - -11/03/2003 mcs@astro.caltech.edu - configure.in configure - Under linux when _POSIX_C_SOURCE is defined, getpwent() - and associated functions become undefined, because - _SVID_SOURCE and _BSD_SOURCE become undefined. Adding - these feature macros back to CFLAGS resolves this. - -06/03/2003 mcs@astro.caltech.edu - getline.c libtecla.map man/func/gl_get_line.in - Following the lead of Edward Chien, I wrote a function - called gl_bind_keyseq(), which binds a specified - key-sequence to a given action, or unbinds the - key-sequence. - -24/02/2003 mcs@astro.caltech.edu - getline.c libtecla.map man/func/cpl_complete_word.in - I implemented a simple function called - cpl_recall_matches(). This recalls the return value of - the last call to cpl_complete_word(). - -19/01/2003 mcs@astro.caltech.edu - getline.c - The documented signal handling, fd event-handling, - inactivity timeout handling, and server-mode non-blocking - I/O features are now implemented for non-interactive - input streams, such as pipes and files. - -19/01/2003 mcs@astro.caltech.edu - getline.c libtecla.h man/func/gl_get_line.in demo3.c - I added a new return status enumerator to report - when an end-of-file condition causes gl_get_line() - to return NULL. - -13/01/2003 mcs@astro.caltech.edu - history.c - I rewrote the history facility. The previous - circular buffer implementation was a nightmare to change, - and it couldn't efficiently support certain newly - requested features. The new implementation stores history - lines in linked lists of fixed sized string segments, - taken from the buffer, with each line being reference - counted and recorded in a hash table. If the user enters - a line multiple times, only one copy of the line is now - stored. Not only does this make better use of the - available buffer space, but it also makes it easy to - ensure that a line whose prefix matches the current - search prefix, isn't returned more than once in sequence, - since we can simply see if the latest search result has - the same hash-table pointer as the previous one, rather - than having to compare strings. Another plus is that due - to the use of linked lists of nodes of fixed size line - segments, there is no longer any need to continually - shuffle the contents of the buffer in order to defragment - it. As far as the user is concerned, the visible - differences are as follows: - - 1. If the user enters a given line multiple times in a - row, each one will be recorded in the history list, - and will thus be listed by gl_show_history(), and - saved in the history file. Previously only one line - was recorded when consecutive duplicates were entered. - This was a kludge to prevent history recall from - recalling the same line multiple times in a row. This - only achieved the desired result when not recalling by - prefix. - - 2. Not only simple recall, but prefix-based history line - recalls now don't return the same line multiple times - in a row. As mentioned in (1) above, previously this - only worked when performing a simple recall, without a - search prefix. - -28/12/2002 mcs@astro.caltech.edu - getline.c - The one-line function, gl_buff_curpos_to_term_curpos() - was only being used by gl_place_cursor(), so I inlined it - in that function, and removed it. - -28/12/2002 mcs@astro.caltech.edu - getline.c - gl_suspend_process() was calling the application-level - gl_normal_io() and gl_raw_io() functions, where it should - have been calling the internal versions _gl_normal_io() - and _gl_raw_io(). - Also gl_handle_signal() was masking and unmasking just - the signals of the first element of the gl[] array - argument. It now masks and unmasks all trappable signals. - -28/12/2002 mcs@astro.caltech.edu - getline.c - Now that the number of terminal characters used to - display the current input line, is recorded, the relative - line on which the last character of the input line - resides can be determined without having to call - gl_buff_curpos_to_term_curpos(). This is now used by - gl_normal_io() via gl_start_newline(), so there is now no - need for gl_buff_curpos_to_term_curpos() to be - async-signal safe. I have thus removed the annoying - gl->cwidth[] array, and gl_buff_curpos_to_term_curpos() - now calls gl_width_of_char() directly again. There is - also now no need for the gl_line_of_char_start() and - gl_line_of_char_end() functions, so I have removed them. - -28/12/2002 mcs@astro.caltech.edu - getline.c - Unfortunately it turns out that the terminfo/termcap - control sequence which is defined to delete everything - from the current position to the end of the terminal, is - only defined to work when at the start of a terminal - line. In gnome terminals in RedHat 8.0, if it is used - within a terminal line, it erases the whole terminal - line, rather than just what follows the cursor. Thus to - portably truncate the displayed input line it is - necessary to first use the control sequence which deletes - from the cursor position to the end of the line, then if - there are more terminal lines, move to the start of the - next line, and use the delete to end-of-terminal control - sequence, then restore the cursor position. This requires - that one know how many physical terminal lines are used - by the current input line, so I now keep a record of the - number of characters so far displayed to the terminal - following the start of the prompt, and the new - gl_truncate_display() function uses this information to - truncate the displayed input line from the current cursor - position. - -28/12/2002 mcs@astro.caltech.edu - getline.c - gl_start_newline() now moves to an empty line following - the input line, rather than just to the next line. It - also arranges for the input line to be redisplayed before - editing resumes. A major user of this is gl_print_info(), - which now need not be followed by an explicit call to - gl_redisplay(), since the terminal input loop in - gl_get_input_line() ensures that gl_redisplay() is called - after any action function that asserts gl->redisplay. - Also, all functions that erase the displayed input line - can now call the gl_erase_line() function, which is - designed to work correctly even when a terminal resize - invalidates the horizontal cursor position. Finally, the - new gl_queue_display() function is now used by functions - that need to arrange for the input line to be displayed - from scratch after the displayed line has been erased or - invalidated by other text being written to the terminal. - All of these changes are aimed at reducing the number of - places that directly modify gl->term_curpos and - gl->redisplay. - -22/12/2002 Markus Gyger (logged here by mcs) - Makefile.in update_html - In places where echo and sed were being used to extract - the base names of files, Markus substituted the basename - command. He also replaced explicit cp and chmod commands - with invokations of the install-sh script. - configure.in - Use $target_os and $target_cpu, where appropriate, - instead of $target. - configure.in - The Solaris man function and library man pages should - be in sections 3lib and 3tecla respectively, only in - Solaris version 2.8 and above. - configure.in - Markus provided values for the man page configuration - variables for HPUX. - man/*/*.in - I had missed parameterizing man page section numbers in - the man page titles, Markus corrected this. - man/func/libtecla_version.in - Fixed incorrect section number in the link to the - libtecla man page. - homedir.c - When compiled to be reentrant, although one can't use the - non-reentrant getpwent() function to scan the password - file for username completions, one can at least see if - the prefix being completed is a valid username, and if - the username of the current user minimally matches the - prefix, and if so list them. I simplified Markus' - modification by adding a prefix argument to the - _hd_scan_user_home_dirs() function, and redefining the - function description accordingly, such that now it - reports only those password file entries who's usernames - minimally match the specified prefix. Without this, it - would have been necessary to peak inside the private data - argument passed in by cf_complete_username(). - Markus also provided code which under Solaris uses the - non-reentrant interfaces if the reentrant version of the - library isn't linked with the threads library. - -19/12/2002 mcs@astro.caltech.edu - Makefile.in - Markus pointed out that LDFLAGS was being picked up by - the configure script, but not then being interpolated - into te Makefile. I have thus added the necessary - assignment to Makefile.in and arranged for the value of - LDFLAGS to be passed on to recursive make's. I also did - the same for CPPFLAGS, which had also been omitted. - -18/12/2002 mcs@astro.caltech.edu - man/* man/*/* configure.in configure Makefile.in - update_html - It turns out that the assignment of man page sections to - topics differs somewhat from system to system, so this is - another thing that needs to be configured by the main - configuration script, rather than being hardwired. All - man pages have now been moved into suitably named - topic-specific sub-directories of the top-level man - directory, and instead of having a numeric suffix, now - have the .in suffix, since they are now preprocessed by - the configure script, in the same fashion as Makefile.in. - Whithin these *.in versions of the man pages, and within - Makefile.in, the installation subdirectory (eg. man1) and - the file-name suffix (eg. 1), are written using - configuration macros, so that they get expanded to the - appropriate tokens when the configure script is run. In - principle, the man pages could also take advantage of - other configuration macros, such as the one which expands - to the library installation directory, to include full - path names to installed files in the documentation, so in - the future this feature could have more uses than just - that of parameterizing man page sections. - -18/12/2002 mcs@astro.caltech.edu - man3 man3/* Makefile.in html/index.html update_html - Markus suggested splitting the gl_get_line(3) man page - into user and developer sections, and also pointed out - that the enhance man page should be in section 1, not - section 3. I have thus created a top-level man - directory in which to place the various sections, and - moved the man3 directory into it. The enhance.3 man page - is now in man/man1/enhance.1. I have extracted all - user-oriented sections from the gl_get_line(3) man page - and placed them in a new man7/tecla.7 man page. - -18/12/2002 mcs@astro.caltech.edu - getline.c - Terminal resizing was broken in normal mode, due to - me forcing the terminal cursor position to zero in the - wrong place in gl_check_caught_signal(). - -14/12/2002 Markus Gyger (logged here by mcs) - configure.in configure - Under Solaris, recent versions of gcc search - /usr/local/include for header files before the system - directories. This caused a problem if ncurses was - installed under Solaris, since the termcap.h include file - in /usr/local/include ended up being used at compile - time, whereas the system default version of the curses - library was used at link time. Since the two libraries - declare tputs() differently, this evoked a complaint from - gcc. Markus came up with a way to force Gnu cpp to move - /usr/local/include to the end of the system-include-file - search path, where it belongs. - -13/12/2002 mcs@astro.caltech.edu - man3/gl_io_mode.3 - I rewrote the man page which documents the new non-blocking - server I/O mode. - -12/12/2002 mcs@astro.caltech.edu - demo3.c - I wrote a new version of demo3.c, using signal handlers - that call gl_handle_signal() and gl_abandon_line(), where - previously in this demo, these functions were called from - the application code. - -05/12/2002 mcs@astro.caltech.edu - getline.c - gl_normal_io(), gl_raw_io() and gl_handle_signal() and - gl_abandon_line() are now signal safe, provided that - signal handlers that call them are installed with sa_mask's - that block all other signals who's handlers call them. - This is the case if gl_tty_signals() is used to install - signal handlers that call any of these functions. - - A major stumbling block that had to be overcome was that - gl_displayed_char_width() calls isprint(), which can't - safely be called from a signal handler (eg. under linux, - the is*() functions all use thread-specific data - facilities to support per-thread locales, and the - thread-specific data facilities aren't signal safe). To - work around this, all functions that modify the - input-line buffer, now do so via accessor functions which - also maintain a parallel array of character widths, for - use by gl_buff_curpos_to_term_curpos() in place of - gl_displayed_char_width(). Other minor problems were the - need to avoid tputs(), who's signal safety isn't defined. - -05/12/2002 Eric Norum (logged here by mcs@astro.caltech.edu) - configure.in - Eric provided the configuration information needed - to build shared libraries under Darwin (Max OS X). - -05/12/2002 Richard Mlynarik (logged here by mcs@astro.caltech.edu) - configure.in - AC_PROG_RANLIB gets the wrong version of ranlib when - cross compiling, so has now been replaced by an - invokation of AC_CHECK_TOOL. In addition, AC_CHECK_TOOL - is also now used to find an appropriate version of LD. - -05/12/2002 mcs@astro.caltech.edu (based on patch by Pankaj Rathore) - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - The new gl_set_term_size() function provides a way - to tell gl_get_line() about changes in the size of - the terminal in cases where the values returned by - ioctl(TIOCGWINSZ) isn't correct. - -05/12/2002 mcs@astro.caltech.edu - getline.c - Rather than calling sprintf() to see how much space would - be needed to print a given number in octal, I wrote a - gl_octal_width() function, for use by - gl_displayed_char_width(). This makes the latter - function async signal safe. - -05/12/2002 mcs@astro.caltech.edu - chrqueue.c - Whenever the buffer is exhausted, and getting a new - buffer node would require a call to malloc(), attempt - to flush the buffer to the terminal. In blocking I/O - mode this means that the buffer never grows. In - non-blocking I/O mode, it just helps keep the buffer - size down. - -05/12/2002 mcs@astro.caltech.edu - freelist.h freelist.c - The new _idle_FreeListNodes() function queries the - number of nodes in the freelist which aren't currently - in use. - -05/12/2002 mcs@astro.caltech.edu - Makefile.stub - This now accepts all of the targets that the configured - makefile does, and after configuring the latter makefile, - it invokes it with the same options. - -03/12/2002 mcs@astro.caltech.edu - mans3/gl_io_mode.3 - I completed the man page for all of the new functions - related to non-blocking I/O. - -01/12/2002 mcs@astro.caltech.edu - man3/gl_get_line.3 - I wrote a long section on reliable signal handling, - explaining how gl_get_line() does this, how to make - use of this in a program, and how to handle signals - reliably when faced with other blocking functions. - This basically documents what I have learnt about - signal handling while working on this library. - -01/12/2002 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - In non-blocking server mode, the gl_replace_prompt() - function can now be used between calls to gl_get_line() - if the application wants to change the prompt of the - line that is being edited. - -01/12/2002 mcs@astro.caltech.edu - man3/gl_get_line.3 - I documented the new gl_return_status() and - gl_error_message() functions. - -01/12/2002 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - Added SIGPOLL and SIGXFSZ to the list of signals that - are trapped by default. These are process termination - signals, so the terminal needs to be restored to a - usable state before they terminate the process. - -27/11/2002 mcs@astro.caltech.edu - getline.c libtecla.h - Completed the essential changes needed to support - non-blocking server-I/O mode. - - The new gl_io_mode() function allows one to switch to - and from non-blocking server-I/O mode. - - The new gl_raw_io() function is used in non-blocking - server-I/O mode to switch the terminal into non-blocking - raw I/O mode. - - The new gl_normal_io() function is used in non-blocking - server-I/O mode to switch the restore the terminal to - a normal, blocking state. This is used to suspend line - input before suspending the process or writing messages - to the terminal. - - The new gl_tty_signals() function installs specified - signals handlers for all signals that suspend, terminate - or resume processes, and also for signals that indicate - that the terminal has been resized. This not only saves - the application from having to keep its own ifdef'd list - of such signals, of which there are many, but it also - makes sure that these signal handlers are registered - correctly. This includes using the sa_mask member of each - sigaction structure to ensure that only one of these - handlers runs at a time. This is essential to avoid the - signal handlers all trying to simultaneously modify - shared global data. - - The new gl_handle_signal() function is provided for - responding (from application level) to signals caught by - the application. It handles process suspension, process - termination and terminal resize signals. - - The new gl_pending_io() function tells the application - what direction of I/O gl_get_line() is currently waiting - for. - - In non-blocking server I/O mode, the new - gl_abandon_line() function can be called between calls to - gl_get_line() to discard an input line and force the next - call to gl_get_line() to start the input of a new line. - - Also, in non-blocking server-I/O gl_get_line() doesn't - attempt to do anything but return when one of the signals - that it is configured to catch is caught. This is - necessary because when in this mode, the application is - required to handle these signals when gl_get_line() is - running, and the default configuration of most of these - signals in gl_get_line() is to restore the terminal then - call the application signal handlers. This would be a - case of too many cooks spoiling the broth, so in this - mode, gl_get_line() always defers to the application's - signal handlers. - -26/11/2002 mcs@astro.caltech.edu - getline.c libtecla.h - I implemented a couple of new functions to support - reliable signal handling, as now documented - (see above) in the gl_get_line(3) man page. - - The new gl_catch_blocked() function tells gl_get_line() - to unblock all configured signals around calls to - long-running functions, not only those that aren't - blocked when gl_get_line() is called. This allows - the caller to implement reliable signal handling, - since the unblocking is only done from within code - protected by sigsetjmp(), which avoids race conditions. - - The new gl_list_signals() function fills a provided - sigset_t with the set of signals that gl_get_line() is - currently configured to catch. This allows callers to - block said signals, such that they are only unblocked by - gl_get_line() when it is waiting for I/O. When used in - conjunction with the gl_catch_blocked() function, this - removes the potential for race conditions. - - Also, when gl_get_line() installs its signal handler, - it uses the sa_mask member of the sigaction structure - to ensure that only one instance of this signal handler - will ever be executing at a time. - -25/11/2002 mcs@astro.caltech.edu (bug reported by Pankaj Rathore) - getline.c - When any history recall action was invoked when the - input line buffer was full, an error message would be - displayed complaining about the length of the string - in the line input buffer being inconsistent with the - specified allocated size. This was because instead of - sending the allocated size of the input line, I was - sending the length excluding the element that is - reserved for the '\0' terminator. Sending it the - correct size corrected the problem. - -24/11/2002 mcs@astro.caltech.edu - getline.c - All public functions which take GetLine objects as - arguments now block signals on entry and restore the - signal mask on return. This was an attempt to make it - safe to call getline functions from signal handlers, but - the fact is that the functions that I really wanted this - to apply to, potentially call malloc(), so this currently - isn't the case. - -23/11/2002 mcs@astro.caltech.edu - getline.c libtecla.h - The new gl_return_status() function returns an enumerated - return status which can be used to query what caused - gl_get_line() to return. - -22/11/2002 mcs@astro.caltech.edu - Most existing .c and .h files, plus errmsg.c errmsg.h - Makefile.rules - Until now, many library functions would report error - messages to stderr. This isn't appropriate for library - functions, so in place of this behavior, error messages - are now recorded in internal ErrMsg objects, and passed - between modules via new module-specific error querying - functions. In addition, errno is now set appropriately. - Thus when gl_get_line() and related functions return an - error, strerror() can be used to look up system errors, - and gl_error_message() can be used to recover a higher level - error message. Note that error messages that are - responses to user actions continue to be reported to the - terminal, as before. - -21/11/2002 mcs@astro.caltech.edu - getline.c keytab.h keytab.c Makefile.rules - I wrote a new version of _kt_lookup_binding() that didn't - require the caller to have access to the innards of a - KeyTab object. This then enabled me to move the definition - of KeyTab objects into keytab.c and make the typedef in - keytab.h opaque. Many nested includes were also moved from - keytab.h into keytab.c. - -05/11/2002 mcs@astro.caltech.edu - getline.c libtecla.map libtecla.h demo3.c - I split the old gl_resize_terminal() function into - two parts, gl_query_size() and gl_update_size(), with - the latter calling the former to get the new terminal - size. - -05/11/2002 mcs@astro.caltech.edu - getline.c - I fixed a long time bug in the terminal resizing code. - When the cursor wasn't on the last terminal line of the - input line, the resizing code would redisplay the - the line one or more lines above where it should be - restored. This was due to an error in the calculation of - the number of lines above the cursor position. - -04/11/2002 mcs@astro.caltech.edu - demo.c demo2.c demo3.c - I used the new gl_display_text() function to display - introductory text at the startup of each of the demo - programs. The text is enclosed within a box of asterixes, - drawn dynamically to fit within the confines of the - available terminal width. - -04/11/2002 mcs@astro.caltech.edu - libtecla.h getline.c ioutil.c ioutil.h Makefile.rules - libtecla.map man3/gl_get_line.3 man3/gl_display_text.3 - Needing a way to display introductory text intelligently - in the demo programs, I wrote and documented the - gl_display_text() function. This justifies arbitrary - length text within the bounds of the terminal width, - with or without optional indentation, prefixes and - suffixes. - -03/11/2002 mcs@astro.caltech.edu - demo3.c Makefile.rules - I wrote a new demonstration program. This program acts - exactly like the main demonstration program, except that - it uses an external event loop instead of using the - gl_get_line() internal event loop. This is thus an example - of the new non-blocking server I/O facility. - -02/11/2002 mcs@astro.caltech.edu - getline.c keytab.c keytab.h libtecla.h man3/gl_get_line.3 - man3/gl_completion_action.3 - I added the ability to register additional word - completion actions via the new function - gl_completion_action(). All action functions now take a - new (void *data) argument, which is stored with the - function in the symbol table of actions. The new - gl_completion_action() function uses this feature to - record dynamically allocated objects containing the - specified completion function and callback data along - with either the gl_complete_word() action function, or - the gl_list_completions() action function. These two - actions continue to use the builtin completion functions - when their data pointer is NULL. - -20/10/2002 mcs@astro.caltech.edu - The following are changes merged from the non-blocking - gl_get_line() development branch. - - getline.c - I wrote a gl_start_newline() function, to replace all of - the explicit calls to output \r\n to stdout. - - Informational messages are now written to the terminal - using a new variadic function called gl_print_info(). - This starts a newline, writes string arguments until a - special argument, GL_END_INFO, is seen, then starts - another newline. - - Changed _output_ to _print_ in the following function - names gl_output_control_sequence(), gl_output_char(), - gl_output_string() and gl_output_raw_string(). - - gl_print_raw_string() now has a length argument, so that - strings that aren't terminated with '\0' can be printed. - - The display of the initial contents of a new line to be - edited has been moved into a new function called - gl_present_line(). - - The gl_get_input_line() function now takes the prompt - string as an argument so that gl_replace_prompt() can be - called from within this function instead of from - gl_get_line(). - - Keyboard input is now buffered in a persistent buffer in - the parent GetLine object. gl_read_character() checks - this for unprocessed characters in preference to calling - gl_read_terminal() to append characters to it. A new - function, gl_discard_chars(), removes processed - characters from this buffer. This change is in - preparation for a non-blocking version of gl_get_line(), - where partially input key-sequences must be stored - between calls to gl_get_line(). - - getline.c getline.h history.c history.h cplmatch.c \ - cplmatch.h expand.c expand.h - All terminal output from gl_get_line() is now routed - through a GL_WRITE_FN() callback function called - gl_write_fn. Internal functions in cplmatch.c, - expand.c and history.c have been created which take - such callbacks to write output. These are used both - by functions in getline.c, to display file completions, - expansions, history etc, and as the internals of existing - public functions in these files that print to stdio - streams. In the latter case an internal stdio - GL_WRITE_FN() callback is substituted, so that the - functions behave as before. - - getline.c chrqueue.c chrqueue.h - The gl_write_fn() callback used by gl_get_line() now - writes to a queue, implemented in chrqueue.c. This queue - is implemented as a list of blocks of buffer segments, - the number of which shrink and grow as - needed. The contents of the queue are flushed to the - terminal via another GL_WRITE_FN() callback passed to the - queue object. Currently gl_get_line() passes an internal - function assigned to gl->flush_fn, called - gl_flush_terminal(), which writes the contents of the - queue to the terminal, and knows how to handle both - blocking and non-blocking I/O. The output queue is - designed to be flushed to the terminal incrementally, and - thereby also facilitates non-blocking I/O. - - getline.c getline.h - gl_get_line() now reads all input via the GL_READ_FN() - callback, assigned to gl->read_fn. Currently this is - set to an internal function called gl_read_terminal(), - which knows how to handle both blocking and - non-blocking I/O. - - getline.c libtecla.h - The new gl_set_nonblocking() function can be used to - enable or disable non-blocking I/O. The default is still - blocking I/O. In non-blocking mode, the terminal is told - not to wait when either reading or writing would block. - gl_get_line() then returns, with a return value of NULL, - but with the terminal left in raw mode, so that the - caller's event loop can detect key presses. The caller - should call gl_return_status() to check whether the NULL - return value was due to an error, lack of input, or - inability to write to the terminal without waiting. If - either reading or writing was said to have blocked, the - user then should check for I/O readiness in the specified - direction before calling gl_get_line() again to - incrementally build up the input line. - -05/08/2002 mcs@astro.caltech.edu - man3/gl_get_line.3 man3/gl_inactivity_timeout.3 - I documented the new gl_inactivity_timeout() function. - -08/07/2002 mcs@astro.caltech.edu - libtecla.h getline.c libtecla.map - I added a new gl_inactivity_timeout() function. On - systems that have the select system call, this provides - the option of registering a function that is then called - whenever no I/O activity has been seen for more than a - specified period of time. Like the gl_watch_fd() - facility, timeout callbacks return a code which tells - gl_get_line() how to proceed after the timeout has been - handled. - -04/07/2002 mcs@astro.caltech.edu (based on a bug report from Michael MacFaden) - getline.c - The internal event handler wasn't responding to write - events on client file descriptors, due to a typo which - resulted in read events being checked for twice, and - writes not checked for at all. - pathutil.c - The amount of space to allocate for pathnames is supposed - to come from PATH_MAX in limits.h, but I had neglected to - include limits.h. This went unnoticed because on most - systems the equivalent number is deduced by calling - pathconf(). Apparently under NetBSD this function doesn't - work correctly over NFS mounts. - -30/05/2002 Version 1.4.1 released. - -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. - -07/05/2002 mcs@astro.caltech.edu (async development branch only) - getline.c - gl_read_character() now caches and reads unprocessed - characters from a key-press lookahead buffer. Whenever - gl_intepret_char() receives a new character which makes - an initially promising key-sequence no longer match the - prefix of any binding, it now simply discards the first - character from the key-press buffer and resets the buffer - pointer so that the next call to gl_read_character() - returns the character that followed it, from the buffer. - getline.c - The part of gl_get_input_line() which preloads, displays - and prepares to edit a new input line, has now been moved - into a function called gl_present_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.6.1/INSTALL b/libtecla-1.6.1/INSTALL deleted file mode 100644 index 14fc62d..0000000 --- a/libtecla-1.6.1/INSTALL +++ /dev/null @@ -1,213 +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 makefile variables which can be -overriden when you run make. - -Configure script options: - - If the users of your package won't benefit from having access to the - tecla man pages, you can shorten the length of time taken to run the - configure script by telling this script not to preprocess the man - pages. This is done as follows. - - ./configure --without-man-pages - - Note that this option also causes the makefile man-page installation - targets to do nothing. - - Similarly, if you don't want your users to have access to the - filesystem while they are editing input lines using gl_get_line(), - then use the following configuration argument. - - ./configure --without-file-actions - - This will completely remove the "expand-filename", "read-from-file", - "read-init-files", and "list-glob" action functions. It will also - arrange that the default behavior of actions such as "complete-word" - and "list-or-eof" be changed to show no completions, instead of the - normal default of showing filename completions. - - If you are using a system that doesn't have a file-system, such as an - embedded system, then libtecla can be built with all code that - accesses the filesystem removed. This will make the library a bit - smaller, and potentially avoid running into problems of missing system - functions related to file-system access. This is done with the - following configuration option. - - ./configure --without-file-system - - Beware that this not only prevents the user from accessing the - filesystem while editing an input line in gl_get_line(), but also - removes all public file-related functions, such as the pathname - expansion module. When using gl_get_line() in this configuration, - the functions that load and save history from and to files, are - stubs that report an error if called upon to read files. The - gl_configure_getline() function can still be called upon to - configure gl_get_line() via its app_string argument, but passing it - a filename in either the app_file or user_file arguments will result - in an error being reported. - -Now lets say that you have your own configuration script in the parent -directory of the libtecla top-level directory, and that you don't want -tecla's man pages to be generated. In your configuration script, you -would first need to have a line similar to the following: - - (cd libtecla; ./configure --without-man-pages) - -Now, from your makefile or whatever script you use to build your -application, you would need to make the tecla library. Assuming that -your makefile or build script is in the parent directory of the -libtecla distribution, then the following line tells make to just -build the non-reentrant, static version of the tecla library, and then -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) - -In this statement the LIBDIR=../lib component means that on installing -the library, the make command should place the library 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.6.1/LICENSE.TERMS b/libtecla-1.6.1/LICENSE.TERMS deleted file mode 100644 index e5d9454..0000000 --- a/libtecla-1.6.1/LICENSE.TERMS +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/Makefile b/libtecla-1.6.1/Makefile deleted file mode 100644 index cf89638..0000000 --- a/libtecla-1.6.1/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -default: - ./configure - $(MAKE) - -distclean: - ./configure --without-man-pages - $(MAKE) $@ - -normal reentrant demos demos_r clean install_lib install_bin install_inc \ - install_man install: - ./configure - $(MAKE) $@ diff --git a/libtecla-1.6.1/Makefile.in b/libtecla-1.6.1/Makefile.in deleted file mode 100644 index 4b7c9c3..0000000 --- a/libtecla-1.6.1/Makefile.in +++ /dev/null @@ -1,272 +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@ - -# Optional flags to pass to the linker. - -LDFLAGS = @LDFLAGS@ - -# Optional C pre-processor flags. - -CPPFLAGS = @CPPFLAGS@ - -# 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 = @DEFS_R@ - -# -# 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)' LDFLAGS=$(LDFLAGS) CPPFLAGS=$(CPPFLAGS) - -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)' LDFLAGS=$(LDFLAGS) CPPFLAGS=$(CPPFLAGS) - -demos: normal - -demos_r: reentrant - -clean: - rm -rf *.o normal_obj reentrant_obj libtecla*.a demo demo[0-9] demo_r demo[0-9]_r enhance *~ man/*~ man/*/*~ html/*~ compile_reentrant compile_normal `/bin/ls -1 man/*/*.in | sed 's/\.in$$//'` - @endings="@SHARED_EXT@ @SHARED_ALT@" ; \ - for alt in $$endings ; do \ - lib="libtecla*$$alt" ; \ - rm -f $$lib; echo rm -f $$lib ; \ - done - -distclean: clean - rm -rf config.cache config.status config.log Makefile libtecla.map.opt \ - autom*.cache - 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) libr_man func_man prog_man misc_man file_man - -libr_man: - if test "@MAKE_MAN_PAGES@"_ = "yes"_; then \ - for template in man/libr/*.in; do \ - page=`basename "$$template" .in`; \ - $(srcdir)/install-sh -c -m 644 man/libr/$$page ${MANDIR}/@LIBR_MANDIR@/$$page.@LIBR_MANEXT@; \ - done ; \ - fi - -func_man: - if test "@MAKE_MAN_PAGES@"_ = "yes"_; then \ - for template in man/func/*.in; do \ - page=`basename "$$template" .in`; \ - $(srcdir)/install-sh -c -m 644 man/func/$$page ${MANDIR}/@FUNC_MANDIR@/$$page.@FUNC_MANEXT@; \ - done ; \ - fi - -prog_man: - if test "@MAKE_MAN_PAGES@"_ = "yes"_; then \ - for template in man/prog/*.in; do \ - page=`basename "$$template" .in`; \ - $(srcdir)/install-sh -c -m 644 man/prog/$$page ${MANDIR}/@PROG_MANDIR@/$$page.@PROG_MANEXT@; \ - done ; \ - fi - -misc_man: - if test "@MAKE_MAN_PAGES@"_ = "yes"_; then \ - for template in man/misc/*.in; do \ - page=`basename "$$template" .in`; \ - $(srcdir)/install-sh -c -m 644 man/misc/$$page ${MANDIR}/@MISC_MANDIR@/$$page.@MISC_MANEXT@; \ - done ; \ - fi - -file_man: - if test "@MAKE_MAN_PAGES@"_ = "yes"_; then \ - for template in man/file/*.in; do \ - page=`basename "$$template" .in`; \ - $(srcdir)/install-sh -c -m 644 man/file/$$page ${MANDIR}/@FILE_MANDIR@/$$page.@FILE_MANEXT@; \ - done ; \ - fi - -install_bin: $(BINDIR) $(PROGRAMS) $(PROGRAMS_R) - progs="$(PROGRAMS) $(PROGRAMS_R)"; \ - for prog in $$progs; do \ - $(srcdir)/install-sh -c -m 755 -s $$prog $(BINDIR)/; \ - done - -install: install_lib install_inc install_man install_bin - -# Make any missing installation directories. - -$(MANDIR) $(LIBDIR) $(INCDIR) $(BINDIR): - $(srcdir)/install-sh -d $@ - chmod ugo+rx $@ diff --git a/libtecla-1.6.1/Makefile.rules b/libtecla-1.6.1/Makefile.rules deleted file mode 100644 index 22508bf..0000000 --- a/libtecla-1.6.1/Makefile.rules +++ /dev/null @@ -1,169 +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 \ - $(OBJDIR)/chrqueue.o $(OBJDIR)/ioutil.o $(OBJDIR)/errmsg.o - -# List the available demonstration programs. - -DEMO_PROGS = demo$(SUFFIX) demo2$(SUFFIX) demo3$(SUFFIX) - -# List all of the programs that this makefile can build. - -PROGS = $(DEMO_PROGS) 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_PROGS) - -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) - -demo3$(SUFFIX): $(OBJDIR)/demo3.o - LD_RUN_PATH="$(LIBDIR):$$LD_RUN_PATH:`pwd`" $(CC) $(CFLAGS) -o $@ \ - $(OBJDIR)/demo3.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 \ - $(srcdir)/ioutil.h $(srcdir)/chrqueue.h $(srcdir)/cplmatch.h \ - $(srcdir)/expand.h $(srcdir)/errmsg.h - $(COMPILE) $(srcdir)/getline.c - -$(OBJDIR)/keytab.o: $(srcdir)/keytab.c $(OBJDIR)/keytab.h \ - $(srcdir)/strngmem.h $(srcdir)/getline.h $(srcdir)/errmsg.h \ - $(srcdir)/hash.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)/ioutil.h \ - $(srcdir)/history.h $(srcdir)/freelist.h $(srcdir)/errmsg.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 $(srcdir)/ioutil.h \ - $(srcdir)/expand.h $(srcdir)/errmsg.h - $(COMPILE) $(srcdir)/expand.c - -$(OBJDIR)/direader.o: $(srcdir)/direader.c $(srcdir)/direader.h \ - $(srcdir)/errmsg.h - $(COMPILE) $(srcdir)/direader.c - -$(OBJDIR)/homedir.o: $(srcdir)/homedir.c $(srcdir)/pathutil.h \ - $(srcdir)/homedir.h $(srcdir)/errmsg.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 $(srcdir)/errmsg.h - $(COMPILE) $(srcdir)/cplfile.c - -$(OBJDIR)/cplmatch.o: $(srcdir)/cplmatch.c $(srcdir)/libtecla.h \ - $(srcdir)/ioutil.h $(srcdir)/stringrp.h $(srcdir)/pathutil.h \ - $(srcdir)/cplfile.h $(srcdir)/cplmatch.h $(srcdir)/errmsg.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 $(errmsg.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)/demo3.o: $(srcdir)/demo3.c $(srcdir)/libtecla.h - $(COMPILE) $(srcdir)/demo3.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 - -$(OBJDIR)/chrqueue.o: $(srcdir)/chrqueue.c $(srcdir)/ioutil.h \ - $(srcdir)/chrqueue.h $(srcdir)/freelist.h $(srcdir)/errmsg.h - $(COMPILE) $(srcdir)/chrqueue.c - -$(OBJDIR)/ioutil.o: $(srcdir)/ioutil.c $(srcdir)/ioutil.h - $(COMPILE) $(srcdir)/ioutil.c - -$(OBJDIR)/errmsg.o: $(srcdir)/errmsg.c $(srcdir)/errmsg.h - $(COMPILE) $(srcdir)/errmsg.c - -#----------------------------------------------------------------------- -# Include file dependencies. -#----------------------------------------------------------------------- - -$(OBJDIR)/keytab.h: $(srcdir)/keytab.h $(srcdir)/libtecla.h - cp $(srcdir)/keytab.h $@ diff --git a/libtecla-1.6.1/Makefile.stub b/libtecla-1.6.1/Makefile.stub deleted file mode 100644 index cf89638..0000000 --- a/libtecla-1.6.1/Makefile.stub +++ /dev/null @@ -1,12 +0,0 @@ -default: - ./configure - $(MAKE) - -distclean: - ./configure --without-man-pages - $(MAKE) $@ - -normal reentrant demos demos_r clean install_lib install_bin install_inc \ - install_man install: - ./configure - $(MAKE) $@ diff --git a/libtecla-1.6.1/PORTING b/libtecla-1.6.1/PORTING deleted file mode 100644 index db39818..0000000 --- a/libtecla-1.6.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.6.1/README b/libtecla-1.6.1/README deleted file mode 100644 index 72541b3..0000000 --- a/libtecla-1.6.1/README +++ /dev/null @@ -1,53 +0,0 @@ -This is version 1.6.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, 2002, 2003, 2004 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.6.1/RELEASE.NOTES b/libtecla-1.6.1/RELEASE.NOTES deleted file mode 100644 index 64f941f..0000000 --- a/libtecla-1.6.1/RELEASE.NOTES +++ /dev/null @@ -1,587 +0,0 @@ -This file lists major changes which accompany each new release. - -Version 1.6.1: - - This is primarily a minor bug-fix release. - - One added feature is the ability to call gl_normal_io() from - callbacks registered by gl_watch_fd() and - gl_inactivity_timeout(). This allows these callbacks to cleanly - suspend line editing before either reading from the terminal, or - writing to the terminal; and then subsequently causes the input line - to be automatically redisplayed, and line-editing to be resumed by - gl_get_line(), as soon as the callback returns. - - Another minor change is that if the terminal type specified in the - TERM environment variable is set to "dumb", gl_get_line() now treats - the terminal as though it were a non-interactive stream, rather than - treating it as a VT100-compatible terminal. This means that it - doesn't either prompt for input, or perform any command-line - editing, even when it really is interacting with a terminal. This is - aimed at the rare situation where a third-pary program that connects - to libtecla through an embedded pseudo-terminal, needs to be forced - to behave as though it weren't talking to a terminal, in order that - it be useable in non-interactive scripts. - - Note that in the previous release, the optional configuration - function, gl_tty_signals(), was incorrectly swapping the suspend and - terminal signal handlers before installing them. - - A configuration problem that prevented select() from being used - under MacOS X, has been fixed. - - Although not documented in the man page, it was meant to be possible - to take the input line that one call to gl_get_line() returned, and - ask the next call to gl_get_line() to present it back to the user - for re-editing, simply by passing the pointer returned by one call - to gl_get_line() as the start_line argument of the next call to - gl_get_line(). This feature unfortunately stopped working in 1.6.0, - so this release restores it, and officially documents it in the man - page documentation of gl_get_line(). - - In the previous version of the library, calling gl_terminal_size() - on a system without SIGWINCH support, would crash the - application. This has been fixed. - - Libtecla now apparently compiles cleanly under IRIX. - -Version 1.6.0: - - This release is primarily a bug-fix release. However there are also - four new functions, so the minor version number has been - incremented to reflect this. - - Two of the new functions are gl_automatic_history() and - gl_append_history(). The former of these functions allows the - application to tell gl_get_line() not to automatically archive - entered lines in the history list. The second of these functions - allows the application to explicitly append a line to the history - list. Thus together, these two functions allow the calling - application to take over control of what is placed in the history - list. - - The third new function is gl_query_char(), which prompts the user - for a single character reply, which the user can then type without - having to hit return to enter it. Unless echoing is disabled, the - character that is entered is then displayed after the prompt, - and a newline is started. - - Finally, the 4th new function is gl_read_char(), which also reads - a single character from the user, but doesn't prompt the user, write - anything to the terminal, or disturb any partially entered input - line. It is thus safe to call this function not only from between - calls to gl_get_line(), but also from application callback - functions, even if gl_normal_io() hasn't been called. - - When using the history-search-backwards or history-search-forwards - actions, if the search prefix that the user typed, contains any of - the *,? or [ globbing characters, it is now treated as a glob - pattern to be matched against historical lines, instead of a simple - prefix. - - I have added a --without-file-system option to the configure - script. This is intended for use in embedded systems that either - don't have filesystems, or where the file-system code in libtecla is - seen as unwanted bloat. See the INSTALL document for details. - - Similarly, I also added a --without-file-actions option to the - configure script. This allows the application author/installer to - prevent users of gl_get_line() from accessing the filesystem with - the builtin actions of gl_get_line(). It does this by removing a - number of action functions, such as expand-filename, and list-glob, - and by changing the default behavior of other actions, such as - complete-word and list-or-eof, to show no completions. - - Now to the bugs that have been fixed. Version 1.5.0 had a lot of big - internal changes, so there are a number of bugs that needed to be - fixed. There was a bug which caused a crash if gl_load_history() - was called multiple times. There was another bug which caused a - prompt not to be displayed on the next line after switching from - reading input from a file to reading from the terminal. Also, in - tecla configuration files, backslash escaped characters within - key-binding key-sequences weren't being escaped. Thus ^\\ got - interpretted as a control-\ followed by a \ character instead of as - a control-\. There was a bug in the history recall mechanism which - caused the search prefix to be forgotten in certain complicated - usage scenarios. There was a minor memory leak in the - gl_configure_getline() function. Finally, if gl_get_line() was - aborted by a signal, or any other abnormal event, the value of errno - which originally indicated what had happened, got zeroed by the - code that restored the terminal to a usable state. Thus the - application couldn't figure out what had caused the error, apart - from by looking at gl_return_status(). All of these bugs have been - fixed. - - In the Makefile, there were a number of places where install-sh was - invoked without a path prefix. This has now been remedied. - - A fully functional workaround for a bug in Solaris' terminal I/O - code has also been implemented. This bug, which only manifested - itself in libtecla's uncommonly used non-blocking server I/O mode, - caused characters entered while in normal I/O mode, between calls to - gl_get_line() to be invisible to the next call to gl_get_line(), - until the user typed at least one more key after raw terminal mode - was restored. - - The Gnu autoconf config.guess and config.sub scripts have been - updated to their latest versions. Apparently the old versions that I - was previously using were too old to know about certain BSD ports. - -Version 1.5.0: - - This release includes several major new features for those using - gl_get_line(), shared library support in Darwin, better cross - compilation support, and various minor bug fixes. - - The biggest new feature is the option of a non-blocking I/O mode, in - which gl_get_line() can safely be called from an application's - external event-loop to incrementally read input lines from the user. - This feature is documented in the gl_io_mode(3) man page. - - In addition, there is now support for the definition of additional - word-completion action functions, which can then be bound to - different keys. See the documentation of the gl_completion_action() - function in the gl_get_line(3) man page. - - Externally defined action functions can also be defined, although - presently they don't have write access to the input line, so they - are restricted to operations that display information text to the - terminal, or modify the environment of the calling application in - some way. See the documentation of the gl_register_action() function - in the gl_get_line(3) man page. - - Some of the non-blocking I/O support functions can also be used for - improved signal handling in the normal blocking mode. In particular, - the gl_list_signals() and gl_catch_blocked() functions make it - easier to write reliable signal handling around gl_get_line(). The - new "RELIABLE SIGNAL HANDLING" section of the gl_get_line(3) man - page is intended as an introduction to this subject. - - Programs can now clear the terminal between calls to gl_get_line(), - by calling the new gl_erase_terminal() function. - - The gl_display_text() function, now used in the demos to display - introductory banners, is provided for formatting text according to - the width of the terminal. - - It is now possible to install inactivity timeout callbacks in - gl_get_line(), using the new gl_inactivity_timeout() function. - - The new gl_set_term_size() function allows the application to - explicitly set the terminal size, for cases, such as when one is - using a terminal at the end of a serial lineq, where the terminal - driver doesn't send the process a SIGWINCH when the terminal size - changes. - - The new gl_bind_keyseq() function provides a convenient - alternative to gl_configure_getline(), for binding or unbinding - one key-sequence at a time. - - gl_get_line()s signal handling, file-descriptor event-handling, - inactivity-timeout handling and server-mode non-blocking I/O - features now not only work when input is coming from a terminal, but - now also work when input is coming from non-interactive streams, - such as files and pipes. - - The history implementation has been re-written to make it more - efficient and easier to modify. The biggest user-level change is - that when recalling history lines using a search prefix, the same - line is no longer returned more than once in a row. Previously this - duplicate elimination only worked when one was recalling a line - without specifying a search prefix, and this was naively performed - by preventing neighboring duplicates from existing in the history - list, rather than by skipping duplicates at search time. - - In previous versions of the library, when gl_get_line() and its - associated public functions detected invalid arguments, or couldn't - allocate memory, etc, error messages were written to stderr. This - isn't appropriate for library functions, so instead of writing such - messages to stderr, these messages are now recorded in buffers - within the affected GetLine object. The latest error message can - then subsequently be queried by calling gl_error_message(). The use - of errno has also been expanded, and a new function called - gl_return_status() has been provided to expand on the cause of the - last return from gl_get_line(). - - User level usage and configuration information has now been split - out of the gl_get_line(3) man page into a separate tecla(7) man - page. The enhance(3) man page has also been renamed to enhance(1). - - When expanding "~/", gl_get_line() now checks for, and returns the - value of the HOME environment variable, if it exists, in preference - to looking up the directory of the current user in the password - file. - - When the terminal was resized to a narrower width, previous versions - of gl_get_line() would redraw the line higher up the terminal. This - bug has been fixed. A bug in history recall has also been fixed, in - which an error message was being generated if one attempted to - recall a line while the cursor was at the end of the longest - possible input line. A more serious bug, in which callbacks - registered by gl_watch_fd() weren't being called for write-events, - has also been fixed. Finally, a few minor fixes have been made to - improve support under QNX and Mac OS X. - - Beware that in this release, much of the underlying code has - undergone some radical re-work, so although backwards compatibility - of all documented features has been preserved, there may be some - lingering bugs that could break existing programs. So, if you plan - to use this version in production code, please test it as far as - possible within your application before releasing it to your - clients, and as always, please report any unexpected behavior. - -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.6.1/chrqueue.c b/libtecla-1.6.1/chrqueue.c deleted file mode 100644 index 346e8f6..0000000 --- a/libtecla-1.6.1/chrqueue.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.h> - -#include "ioutil.h" -#include "chrqueue.h" -#include "freelist.h" -#include "errmsg.h" - -/* - * Set the number of bytes allocated to each node of the list of - * character buffers. This facility is designed principally as - * an expandible I/O output buffer, so use the stdio buffer size - * where available. - */ -#ifdef BUFSIZ -#define GL_CQ_SIZE BUFSIZ -#else -#define GL_CQ_SIZE 512 -#endif - -/* - * The queue is contained in a list of fixed sized buffers. New nodes - * are appended to this list as needed to accomodate newly added bytes. - * Old nodes at the head of the list are removed as they are emptied. - */ -typedef struct CqCharBuff CqCharBuff; -struct CqCharBuff { - CqCharBuff *next; /* The next node in the list of buffers */ - char bytes[GL_CQ_SIZE]; /* The fixed size buffer of this node */ -}; - -/* - * Define the structure that is used to contain a list of character - * buffers. - */ -struct GlCharQueue { - ErrMsg *err; /* A buffer in which to record error messages */ - FreeList *bufmem; /* A free-list of CqCharBuff structures */ - struct { - CqCharBuff *head; /* The head of the list of output buffers */ - CqCharBuff *tail; /* The tail of the list of output buffers */ - } buffers; - int nflush; /* The total number of characters that have been */ - /* flushed from the start of the queue since */ - /* _glq_empty_queue() was last called. */ - int ntotal; /* The total number of characters that have been */ - /* appended to the queue since _glq_empty_queue() */ - /* was last called. */ -}; - -/*....................................................................... - * Create a new GlCharQueue object. - * - * Output: - * return GlCharQueue * The new object, or NULL on error. - */ -GlCharQueue *_new_GlCharQueue(void) -{ - GlCharQueue *cq; /* The object to be returned */ -/* - * Allocate the container. - */ - cq = malloc(sizeof(GlCharQueue)); - if(!cq) { - errno = ENOMEM; - 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_GlCharQueue(). - */ - cq->err = NULL; - cq->bufmem = NULL; - cq->buffers.head = NULL; - cq->buffers.tail = NULL; - cq->nflush = cq->ntotal = 0; -/* - * Allocate a place to record error messages. - */ - cq->err = _new_ErrMsg(); - if(!cq->err) - return _del_GlCharQueue(cq); -/* - * Allocate the freelist of CqCharBuff structures. - */ - cq->bufmem = _new_FreeList(sizeof(CqCharBuff), 1); - if(!cq->bufmem) - return _del_GlCharQueue(cq); - return cq; -} - -/*....................................................................... - * Delete a GlCharQueue object. - * - * Input: - * cq GlCharQueue * The object to be deleted. - * Output: - * return GlCharQueue * The deleted object (always NULL). - */ -GlCharQueue *_del_GlCharQueue(GlCharQueue *cq) -{ - if(cq) { - cq->err = _del_ErrMsg(cq->err); - cq->bufmem = _del_FreeList(cq->bufmem, 1); - free(cq); - }; - return NULL; -} - -/*....................................................................... - * Append an array of n characters to a character queue. - * - * Input: - * cq GlCharQueue * The queue to append to. - * chars const char * The array of n characters to be appended. - * n int The number of characters in chars[]. - * write_fn GL_WRITE_FN * The function to call to output characters, - * or 0 to simply discard the contents of the - * queue. This will be called whenever the - * buffer becomes full. If it fails to release - * any space, the buffer will be extended. - * data void * Anonymous data to pass to write_fn(). - * Output: - * return int The number of characters successfully - * appended. This will only be < n on error. - */ -int _glq_append_chars(GlCharQueue *cq, const char *chars, int n, - GlWriteFn *write_fn, void *data) -{ - int ndone = 0; /* The number of characters appended so far */ -/* - * Check the arguments. - */ - if(!cq || !chars) { - errno = EINVAL; - return 0; - }; -/* - * The appended characters may have to be split between multiple - * buffers, so loop for each buffer. - */ - while(ndone < n) { - int ntodo; /* The number of characters remaining to be appended */ - int nleft; /* The amount of space remaining in cq->buffers.tail */ - int nnew; /* The number of characters to append to cq->buffers.tail */ -/* - * Compute the offset at which the next character should be written - * into the tail buffer segment. - */ - int boff = cq->ntotal % GL_CQ_SIZE; -/* - * Since we don't allocate a new buffer until we have at least one - * character to write into it, if boff is 0 at this point, it means - * that we hit the end of the tail buffer segment on the last append, - * so we need to allocate a new one. - * - * If allocating this new node will require a call to malloc(), as - * opposed to using a currently unused node in the freelist, first try - * flushing the current contents of the buffer to the terminal. When - * write_fn() uses blocking I/O, this stops the buffer size ever getting - * bigger than a single buffer node. When it is non-blocking, it helps - * to keep the amount of memory, but it isn't gauranteed to do so. - */ - if(boff == 0 && _idle_FreeListNodes(cq->bufmem) == 0) { - switch(_glq_flush_queue(cq, write_fn, data)) { - case GLQ_FLUSH_DONE: - break; - case GLQ_FLUSH_AGAIN: - errno = 0; /* Don't confuse the caller */ - break; - default: - return ndone; /* Error */ - }; - boff = cq->ntotal % GL_CQ_SIZE; - }; -/* - * Since we don't allocate a new buffer until we have at least one - * character to write into it, if boff is 0 at this point, it means - * that we hit the end of the tail buffer segment on the last append, - * so we need to allocate a new one. - */ - if(boff == 0) { -/* - * Allocate the new node. - */ - CqCharBuff *node = (CqCharBuff *) _new_FreeListNode(cq->bufmem); - if(!node) { - _err_record_msg(cq->err, "Insufficient memory to buffer output.", - END_ERR_MSG); - return ndone; - }; -/* - * Initialize the node. - */ - node->next = NULL; -/* - * Append the new node to the tail of the list. - */ - if(cq->buffers.tail) - cq->buffers.tail->next = node; - else - cq->buffers.head = node; - cq->buffers.tail = node; - }; -/* - * How much room is there for new characters in the current tail node? - */ - nleft = GL_CQ_SIZE - boff; -/* - * How many characters remain to be appended? - */ - ntodo = n - ndone; -/* - * How many characters should we append to the current tail node? - */ - nnew = nleft < ntodo ? nleft : ntodo; -/* - * Append the latest prefix of nnew characters. - */ - memcpy(cq->buffers.tail->bytes + boff, chars + ndone, nnew); - cq->ntotal += nnew; - ndone += nnew; - }; -/* - * Return the count of the number of characters successfully appended. - */ - return ndone; -} - -/*....................................................................... - * Discard the contents of a queue of characters. - * - * Input: - * cq GlCharQueue * The queue to clear. - */ -void _glq_empty_queue(GlCharQueue *cq) -{ - if(cq) { -/* - * Return all list nodes to their respective free-lists. - */ - _rst_FreeList(cq->bufmem); -/* - * Mark the lists as empty. - */ - cq->buffers.head = cq->buffers.tail = NULL; - cq->nflush = cq->ntotal = 0; - }; -} - -/*....................................................................... - * Return a count of the number of characters currently in the queue. - * - * Input: - * cq GlCharQueue * The queue of interest. - * Output: - * return int The number of characters in the queue. - */ -int _glq_char_count(GlCharQueue *cq) -{ - return (cq && cq->buffers.head) ? (cq->ntotal - cq->nflush) : 0; -} - -/*....................................................................... - * Write as many characters as possible from the start of a character - * queue via a given output callback function, removing those written - * from the queue. - * - * Input: - * cq GlCharQueue * The queue to write characters from. - * write_fn GL_WRITE_FN * The function to call to output characters, - * or 0 to simply discard the contents of the - * queue. - * data void * Anonymous data to pass to write_fn(). - * Output: - * return GlFlushState The status of the flush operation: - * GLQ_FLUSH_DONE - The flush operation - * completed successfully. - * GLQ_FLUSH_AGAIN - The flush operation - * couldn't be completed - * on this call. Call this - * function again when the - * output channel can accept - * further output. - * GLQ_FLUSH_ERROR Unrecoverable error. - */ -GlqFlushState _glq_flush_queue(GlCharQueue *cq, GlWriteFn *write_fn, - void *data) -{ -/* - * Check the arguments. - */ - if(!cq) { - errno = EINVAL; - return GLQ_FLUSH_ERROR; - }; -/* - * If possible keep writing until all of the chained buffers have been - * emptied and removed from the list. - */ - while(cq->buffers.head) { -/* - * Are we looking at the only node in the list? - */ - int is_tail = cq->buffers.head == cq->buffers.tail; -/* - * How many characters more than an exact multiple of the buffer-segment - * size have been added to the buffer so far? - */ - int nmodulo = cq->ntotal % GL_CQ_SIZE; -/* - * How many characters of the buffer segment at the head of the list - * have been used? Note that this includes any characters that have - * already been flushed. Also note that if nmodulo==0, this means that - * the tail buffer segment is full. The reason for this is that we - * don't allocate new tail buffer segments until there is at least one - * character to be added to them. - */ - int nhead = (!is_tail || nmodulo == 0) ? GL_CQ_SIZE : nmodulo; -/* - * How many characters remain to be flushed from the buffer - * at the head of the list? - */ - int nbuff = nhead - (cq->nflush % GL_CQ_SIZE); -/* - * Attempt to write this number. - */ - int nnew = write_fn(data, cq->buffers.head->bytes + - cq->nflush % GL_CQ_SIZE, nbuff); -/* - * Was anything written? - */ - if(nnew > 0) { -/* - * Increment the count of the number of characters that have - * been flushed from the head of the queue. - */ - cq->nflush += nnew; -/* - * If we succeded in writing all of the contents of the current - * buffer segment, remove it from the queue. - */ - if(nnew == nbuff) { -/* - * If we just emptied the last node left in the list, then the queue is - * now empty and should be reset. - */ - if(is_tail) { - _glq_empty_queue(cq); - } else { -/* - * Get the node to be removed from the head of the list. - */ - CqCharBuff *node = cq->buffers.head; -/* - * Make the node that follows it the new head of the queue. - */ - cq->buffers.head = node->next; -/* - * Return it to the freelist. - */ - node = (CqCharBuff *) _del_FreeListNode(cq->bufmem, node); - }; - }; -/* - * If the write blocked, request that this function be called again - * when space to write next becomes available. - */ - } else if(nnew==0) { - return GLQ_FLUSH_AGAIN; -/* - * I/O error. - */ - } else { - _err_record_msg(cq->err, "Error writing to terminal", END_ERR_MSG); - return GLQ_FLUSH_ERROR; - }; - }; -/* - * To get here the queue must now be empty. - */ - return GLQ_FLUSH_DONE; -} - -/*....................................................................... - * Return extra information (ie. in addition to that provided by errno) - * about the last error to occur in any of the public functions of this - * module. - * - * Input: - * cq GlCharQueue * The container of the history list. - * Output: - * return const char * A pointer to the internal buffer in which - * the error message is temporarily stored. - */ -const char *_glq_last_error(GlCharQueue *cq) -{ - return cq ? _err_get_msg(cq->err) : "NULL GlCharQueue argument"; -} diff --git a/libtecla-1.6.1/chrqueue.h b/libtecla-1.6.1/chrqueue.h deleted file mode 100644 index 1aca8e0..0000000 --- a/libtecla-1.6.1/chrqueue.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef chrqueue_h -#define chrqueue_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 implements a queue of characters to be processed in some - * way. It is used by gl_get_line() to maintain a queue of characters - * to be sent to a remote terminal. Characters are recorded in a - * dynamically extensible list of fixed sized buffers. - */ - -typedef struct GlCharQueue GlCharQueue; - -/* - * Create a new character queue. - */ -GlCharQueue *_new_GlCharQueue(void); - -/* - * Delete a redundant character queue. - */ -GlCharQueue *_del_GlCharQueue(GlCharQueue *cq); - -/* - * Append an array of n characters to a character queue. - */ -int _glq_append_chars(GlCharQueue *cq, const char *chars, int n, - GlWriteFn *write_fn, void *data); - -/* - * Clear a character queue. - */ -void _glq_empty_queue(GlCharQueue *cq); - -/* - * Return a count of the number of characters in the queue. - */ -int _glq_char_count(GlCharQueue *cq); - -/* - * A structure of the following type is used by _glq_peek_chars() to - * return characters at the start of the queue. - */ -typedef struct { - const char *buff; /* A pointer to the first undeleted byte in the */ - /* first buffer of the queue. */ - int nbuff; /* The number of characters in buff[] */ -} GlCharQueueBuff; - -/* - * Enumerator values of the following type are returned by - * _glq_flush_queue() to indicate the status of the flush operation. - */ -typedef enum { - GLQ_FLUSH_DONE, /* The flush operation completed successfully */ - GLQ_FLUSH_AGAIN, /* The flush operation couldn't be completed on this */ - /* call. Call this function again when the output */ - /* channel can accept further output. */ - GLQ_FLUSH_ERROR /* Unrecoverable error. */ -} GlqFlushState; - -/* - * Transfer as much of the contents of a character queue to an output - * channel as possible, returning before the queue is empty if the - * write_fn() callback says that it can't currently write anymore. - */ -GlqFlushState _glq_flush_queue(GlCharQueue *cq, GlWriteFn *write_fn, - void *data); - -/* - * Provide information about the last error that occurred while calling - * any of the above functions. - */ -const char *_glq_last_error(GlCharQueue *cq); - -#endif diff --git a/libtecla-1.6.1/config.guess b/libtecla-1.6.1/config.guess deleted file mode 100644 index 500ee74..0000000 --- a/libtecla-1.6.1/config.guess +++ /dev/null @@ -1,1410 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -timestamp='2003-10-03' - -# 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. - -# Originally written by Per Bothner <per@bothner.com>. -# Please send patches to <config-patches@gnu.org>. Submit a context -# diff and a properly formatted ChangeLog entry. -# -# 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 build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to <config-patches@gnu.org>." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -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 - -# 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. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - 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 - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # 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 ;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - macppc:OpenBSD:*:*) - echo powerpc-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 ;; - mvmeppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mipseb-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sun3:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # 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. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha*:OpenVMS:*:*) - echo alpha-hp-vms - 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-unknown-sysv4 - exit 0;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - 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:*:* | SR8000: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 ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit 0 ;; - DRS?6000:UNIX_SV:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7 && exit 0 ;; - esac ;; - 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=`(sed 1q /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 ;; - # 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 ;; - 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) - eval $set_cc_for_build - 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 -o $dummy $dummy.c \ - && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && exit 0 - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit 0 ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - 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 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - 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 -o $dummy $dummy.c && $dummy && exit 0 - 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:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${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=${UNAME_VERSION}.${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:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - 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 -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - # avoid double evaluation of $set_cc_for_build - test -n "$CC_FOR_BUILD" || eval $set_cc_for_build - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - 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 -o $dummy $dummy.c && $dummy && exit 0 - 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:*:* | *3000*: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 ;; - 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*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - 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/ \ - -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - *:UNICOS/mp:*:*) - echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - 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:*:*|*:GNU/FreeBSD:*:*) - # Determine whether the default compiler uses glibc. - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include <features.h> - #if __GLIBC__ >= 2 - LIBC=gnu - #else - LIBC= - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - # GNU/FreeBSD systems have a "k" prefix to indicate we are using - # FreeBSD's kernel, but not the complete OS. - case ${LIBC} in gnu) kernel_only='k' ;; esac - echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - x86:Interix*:[34]*) - echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' - exit 0 ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - 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 i586-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 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86: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. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include <features.h> - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #ifdef __INTEL_COMPILER - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; - i*86:DYNIX/ptx:4*:*) - # 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. - 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:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - 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:[78]*) - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - 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|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - 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 ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit 0 ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*: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.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-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:*: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 ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - 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 ;; - SX-6:SUPER-UX:*:*) - echo sx6-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:*:*) - case `uname -p` in - *86) UNAME_PROCESSOR=i686 ;; - powerpc) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-[DGKLNPTVWY]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${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 - -eval $set_cc_for_build -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) -# include <sys/param.h> -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# 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 -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 - -# 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 - -cat >&2 <<EOF -$0: unable to guess system type - -This script, last modified $timestamp, has failed to recognize -the operating system you are using. It is advised that you -download the most up to date version of the config scripts from - - ftp://ftp.gnu.org/pub/gnu/config/ - -If the version you run ($0) is already up to date, please -send the following data and any information you think might be -pertinent to <config-patches@gnu.org> in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/libtecla-1.6.1/config.sub b/libtecla-1.6.1/config.sub deleted file mode 100644 index 1f31816..0000000 --- a/libtecla-1.6.1/config.sub +++ /dev/null @@ -1,1510 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -timestamp='2003-08-18' - -# 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. - -# Please send patches to <config-patches@gnu.org>. Submit a context -# diff and a properly formatted ChangeLog entry. -# -# 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. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to <config-patches@gnu.org>." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -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* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) - 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 | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - 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. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | msp430 \ - | ns16k | ns32k \ - | openrisc | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xscale | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - - # 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*86 | x86_64) - 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. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32r-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; - # 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 - ;; - amd64) - basic_machine=x86_64-pc - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - 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 - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - 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 | j90) - basic_machine=j90-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - 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 - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - 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*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*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 - ;; - 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 - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - 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 - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - 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 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - or32 | or32-*) - basic_machine=or32-unknown - os=-coff - ;; - 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 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-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/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-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=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - 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 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - 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 - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparc | sparcv9 | sparcv9b) - 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 - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - 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* | -kfreebsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|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-dietlibc) - os=-linux-dietlibc - ;; - -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 - ;; - -atheos*) - os=-atheos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -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[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -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 - ;; - c4x-* | tic4x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - 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 - ;; - or32-*) - os=-coff - ;; - *-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 - ;; - f30[01]-fujitsu | f700-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* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/libtecla-1.6.1/configure b/libtecla-1.6.1/configure deleted file mode 100755 index 62f49e0..0000000 --- a/libtecla-1.6.1/configure +++ /dev/null @@ -1,5208 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.57. -# -# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 -# Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi - -# Support unset when possible. -if (FOO=FOO; unset FOO) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -exec 6>&1 - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_config_libobj_dir=. -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} - -# Identity of this package. -PACKAGE_NAME= -PACKAGE_TARNAME= -PACKAGE_VERSION= -PACKAGE_STRING= -PACKAGE_BUGREPORT= - -ac_unique_file="getline.c" -# Factoring default headers for most tests. -ac_includes_default="\ -#include <stdio.h> -#if HAVE_SYS_TYPES_H -# include <sys/types.h> -#endif -#if HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif -#if STDC_HEADERS -# include <stdlib.h> -# include <stddef.h> -#else -# if HAVE_STDLIB_H -# include <stdlib.h> -# endif -#endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H -# include <memory.h> -# endif -# include <string.h> -#endif -#if HAVE_STRINGS_H -# include <strings.h> -#endif -#if HAVE_INTTYPES_H -# include <inttypes.h> -#else -# if HAVE_STDINT_H -# include <stdint.h> -# endif -#endif -#if HAVE_UNISTD_H -# include <unistd.h> -#endif" - -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAJOR_VER MINOR_VER MICRO_VER CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SET_MAKE LN_S AWK RANLIB ac_ct_RANLIB LD ac_ct_LD build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CPP EGREP TARGETS SHARED_EXT SHARED_ALT SHARED_CFLAGS LINK_SHARED DEFS_R LIBR_MANDIR LIBR_MANEXT FUNC_MANDIR FUNC_MANEXT PROG_MANDIR PROG_MANEXT MISC_MANDIR MISC_MANEXT FILE_MANDIR FILE_MANEXT TARGET_LIBS MAKE_MAN_PAGES LIBOBJS LTLIBOBJS' -ac_subst_files='' - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -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' - -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 - - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - - # 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_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$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 ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) 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 | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$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 | -n) - 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_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "with_$ac_package='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - 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 "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -# 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_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - 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 "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi -fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS -ac_env_CPP_set=${CPP+set} -ac_env_CPP_value=$CPP -ac_cv_env_CPP_set=${CPP+set} -ac_cv_env_CPP_value=$CPP - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # 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 <<_ACEOF -\`configure' configures this package to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -_ACEOF - - cat <<_ACEOF -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] -_ACEOF - - cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] -_ACEOF -fi - -if test -n "$ac_init_help"; then - - cat <<\_ACEOF - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-file-actions Should users of gl_get_line() have access to the - filesystem (default=yes) - --with-file-system Does the target have a filesystem (default=yes) - --with-man-pages Are man pages desired (default=yes) - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a - nonstandard directory <lib dir> - CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have - headers in a nonstandard directory <include dir> - CPP C preprocessor - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -_ACEOF -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - ac_popdir=`pwd` - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd $ac_popdir - done -fi - -test -n "$ac_init_help" && exit 0 -if $ac_init_version; then - cat <<\_ACEOF - -Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 -Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit 0 -fi -exec 5>config.log -cat >&5 <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by $as_me, which was -generated by GNU Autoconf 2.57. Invocation command line was - - $ $0 $@ - -_ACEOF -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_sep= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -{ - (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) - sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; - *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - sed "/^$/d" confdefs.h | sort - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core core.* *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status - ' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# 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 - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# 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 "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . $cache_file;; - *) . ./$cache_file;; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - - - - - -MAJOR_VER="1" - - - -MINOR_VER="6" - - - -MICRO_VER="1" - - -CFLAGS="$CFLAGS" -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -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 "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -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 $# != 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 - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -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 "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 - (eval $ac_compiler --version </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 - (eval $ac_compiler -v </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 - (eval $ac_compiler -V </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -echo "$as_me:$LINENO: checking for C compiler default output" >&5 -echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; - * ) - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 - -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&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 "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdarg.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - ''\ - '#include <stdlib.h>' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdlib.h> -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` -if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.make <<\_ACEOF -all: - @echo 'ac_maketemp="$(MAKE)"' -_ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftest.make 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 conftest.make -fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - SET_MAKE= -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - SET_MAKE="MAKE=${MAKE-make}" -fi - - - -echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else - echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&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 "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_AWK+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - echo "$as_me:$LINENO: result: $AWK" >&5 -echo "${ECHO_T}$AWK" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$AWK" && break -done - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - RANLIB=$ac_ct_RANLIB -else - RANLIB="$ac_cv_prog_RANLIB" -fi - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. -set dummy ${ac_tool_prefix}ld; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$LD"; then - ac_cv_prog_LD="$LD" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_LD="${ac_tool_prefix}ld" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -LD=$ac_cv_prog_LD -if test -n "$LD"; then - echo "$as_me:$LINENO: result: $LD" >&5 -echo "${ECHO_T}$LD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_LD"; then - ac_ct_LD=$LD - # Extract the first word of "ld", so it can be a program name with args. -set dummy ld; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_LD"; then - ac_cv_prog_ac_ct_LD="$ac_ct_LD" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_LD="ld" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_LD=$ac_cv_prog_ac_ct_LD -if test -n "$ac_ct_LD"; then - echo "$as_me:$LINENO: result: $ac_ct_LD" >&5 -echo "${ECHO_T}$ac_ct_LD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - LD=$ac_ct_LD -else - LD="$ac_cv_prog_LD" -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 - elif test -f $ac_dir/shtool; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 -echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} - { (exit 1); exit 1; }; } -fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. - -# Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } - -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 -build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 -host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -echo "$as_me:$LINENO: checking target system type" >&5 -echo $ECHO_N "checking target system type... $ECHO_C" >&6 -if test "${ac_cv_target+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_target_alias=$target_alias -test "x$ac_cv_target_alias" = "x" && - ac_cv_target_alias=$ac_cv_host_alias -ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_target" >&5 -echo "${ECHO_T}$ac_cv_target" >&6 -target=$ac_cv_target -target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - - -case $target_os in -solaris2.[0-6]|solaris2.[0-6].*) - LIBS="$LIBS -L/usr/ccs/lib" - ;; -esac - - -if test "$GCC"_ = "yes"_; then - touch foo.c - fix=`$CC -E -Wp,-v foo.c 2>&1 | $AWK ' - /^#include <...> search starts here:/ {in_list=1;ndir=0} - / *\// && in_list {path[ndir++] = $1} - /^End of search list/ {in_list=0} - END { - if(path[0] ~ /\/usr\/local\/include/) { - for(dir=1; dir<ndir; dir++) { - printf(" -isystem %s", path[dir]) - } - printf("\n"); - } - }'` - rm -f foo.c - CFLAGS="$CFLAGS$fix" -fi - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6 -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep - - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ctype.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -echo "$as_me:$LINENO: checking for tigetstr in -lcurses" >&5 -echo $ECHO_N "checking for tigetstr in -lcurses... $ECHO_C" >&6 -if test "${ac_cv_lib_curses_tigetstr+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcurses $LIBS" -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* 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; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_curses_tigetstr=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_curses_tigetstr=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_curses_tigetstr" >&5 -echo "${ECHO_T}$ac_cv_lib_curses_tigetstr" >&6 -if test $ac_cv_lib_curses_tigetstr = yes; then - - cat >>confdefs.h <<\_ACEOF -#define USE_TERMINFO 1 -_ACEOF - - LIBS="$LIBS -lcurses" - -else - echo "$as_me:$LINENO: checking for tigetstr in -lncurses" >&5 -echo $ECHO_N "checking for tigetstr in -lncurses... $ECHO_C" >&6 -if test "${ac_cv_lib_ncurses_tigetstr+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lncurses $LIBS" -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* 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; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_ncurses_tigetstr=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_ncurses_tigetstr=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_tigetstr" >&5 -echo "${ECHO_T}$ac_cv_lib_ncurses_tigetstr" >&6 -if test $ac_cv_lib_ncurses_tigetstr = yes; then - - cat >>confdefs.h <<\_ACEOF -#define USE_TERMINFO 1 -_ACEOF - - LIBS="$LIBS -lncurses" - -else - echo "$as_me:$LINENO: checking for tgetstr in -lcurses" >&5 -echo $ECHO_N "checking for tgetstr in -lcurses... $ECHO_C" >&6 -if test "${ac_cv_lib_curses_tgetstr+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcurses $LIBS" -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* 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; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_curses_tgetstr=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_curses_tgetstr=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_curses_tgetstr" >&5 -echo "${ECHO_T}$ac_cv_lib_curses_tgetstr" >&6 -if test $ac_cv_lib_curses_tgetstr = yes; then - - cat >>confdefs.h <<\_ACEOF -#define USE_TERMCAP 1 -_ACEOF - - LIBS="$LIBS -lcurses" - if test "${ac_cv_header_termcap_h+set}" = set; then - echo "$as_me:$LINENO: checking for termcap.h" >&5 -echo $ECHO_N "checking for termcap.h... $ECHO_C" >&6 -if test "${ac_cv_header_termcap_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_termcap_h" >&5 -echo "${ECHO_T}$ac_cv_header_termcap_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking termcap.h usability" >&5 -echo $ECHO_N "checking termcap.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <termcap.h> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking termcap.h presence" >&5 -echo $ECHO_N "checking termcap.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <termcap.h> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc in - yes:no ) - { echo "$as_me:$LINENO: WARNING: termcap.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: termcap.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: termcap.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: termcap.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; - no:yes ) - { echo "$as_me:$LINENO: WARNING: termcap.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: termcap.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: termcap.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: termcap.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: termcap.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: termcap.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for termcap.h" >&5 -echo $ECHO_N "checking for termcap.h... $ECHO_C" >&6 -if test "${ac_cv_header_termcap_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_termcap_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_termcap_h" >&5 -echo "${ECHO_T}$ac_cv_header_termcap_h" >&6 - -fi -if test $ac_cv_header_termcap_h = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_TERMCAP_H 1 -_ACEOF - -fi - - - -fi - -fi - -fi - - - - -for ac_header in curses.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc in - yes:no ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; - no:yes ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -for ac_header in term.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <curses.h> - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -else - -for ac_header in ncurses/curses.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc in - yes:no ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; - no:yes ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -for ac_header in ncurses/term.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ncurses/curses.h> - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -fi - -done - -fi - -done - - - - -TARGETS="normal reentrant" - - -echo "$as_me:$LINENO: checking for reentrant functions" >&5 -echo $ECHO_N "checking for reentrant functions... $ECHO_C" >&6 -if test "${tecla_cv_reentrant+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - KEPT_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199506L" - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end 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; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - tecla_cv_reentrant=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -tecla_cv_reentrant=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext - CFLAGS="$KEPT_CFLAGS" - -fi -echo "$as_me:$LINENO: result: $tecla_cv_reentrant" >&5 -echo "${ECHO_T}$tecla_cv_reentrant" >&6 - - -if test $tecla_cv_reentrant = no; then - TARGETS="normal" -fi - - -if test "${ac_cv_header_sys_select_h+set}" = set; then - echo "$as_me:$LINENO: checking for sys/select.h" >&5 -echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6 -if test "${ac_cv_header_sys_select_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_select_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_select_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking sys/select.h usability" >&5 -echo $ECHO_N "checking sys/select.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <sys/select.h> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking sys/select.h presence" >&5 -echo $ECHO_N "checking sys/select.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <sys/select.h> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc in - yes:no ) - { echo "$as_me:$LINENO: WARNING: sys/select.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: sys/select.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/select.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: sys/select.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; - no:yes ) - { echo "$as_me:$LINENO: WARNING: sys/select.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: sys/select.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/select.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: sys/select.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/select.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: sys/select.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for sys/select.h" >&5 -echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6 -if test "${ac_cv_header_sys_select_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_sys_select_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_select_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_select_h" >&6 - -fi -if test $ac_cv_header_sys_select_h = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SYS_SELECT_H 1 -_ACEOF - -fi - - - - -echo "$as_me:$LINENO: checking for select system call" >&5 -echo $ECHO_N "checking for select system call... $ECHO_C" >&6 -if test "${tecla_cv_select+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -int -main () -{ - - fd_set fds; - int nready; - FD_ZERO(&fds); - FD_SET(1, &fds); - nready = select(2, &fds, &fds, &fds, NULL); - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - tecla_cv_select=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -tecla_cv_select=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext - -fi -echo "$as_me:$LINENO: result: $tecla_cv_select" >&5 -echo "${ECHO_T}$tecla_cv_select" >&6 - - -if test $tecla_cv_select = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SELECT 1 -_ACEOF - -fi - - -echo "$as_me:$LINENO: checking for SysV pseudo-terminals" >&5 -echo $ECHO_N "checking for SysV pseudo-terminals... $ECHO_C" >&6 -if test "${tecla_cv_sysv_pty+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end 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; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - tecla_cv_sysv_pty=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -tecla_cv_sysv_pty=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext - -fi -echo "$as_me:$LINENO: result: $tecla_cv_sysv_pty" >&5 -echo "${ECHO_T}$tecla_cv_sysv_pty" >&6 - - -if test $tecla_cv_sysv_pty = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SYSV_PTY 1 -_ACEOF - -fi - - - -SHARED_EXT="" - - - -SHARED_ALT="" - - - -SHARED_CFLAGS="" - - - -LINK_SHARED="" - - - -DEFS_R="-D_POSIX_C_SOURCE=199506L -DPREFER_REENTRANT" - - - - -LIBR_MANDIR="man3" -LIBR_MANEXT="3" - - - - -FUNC_MANDIR="man3" -FUNC_MANEXT="3" - - - - -PROG_MANDIR="man1" -PROG_MANEXT="1" - - - - -MISC_MANDIR="man7" -MISC_MANEXT="7" - - - - -FILE_MANDIR="man5" -FILE_MANEXT="5" - - - -# Check whether --with-file-actions or --without-file-actions was given. -if test "${with_file_actions+set}" = set; then - withval="$with_file_actions" - cat >>confdefs.h <<\_ACEOF -#define HIDE_FILE_SYSTEM 1 -_ACEOF - -fi; - - - -# Check whether --with-file-system or --without-file-system was given. -if test "${with_file_system+set}" = set; then - withval="$with_file_system" - cat >>confdefs.h <<\_ACEOF -#define WITHOUT_FILE_SYSTEM 1 -_ACEOF - -fi; - - -case $target in -*solaris*) - cat >>confdefs.h <<\_ACEOF -#define __EXTENSIONS__ 1 -_ACEOF - - 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" ;; - esac - case $target_cpu in - sparc) SHARED_CFLAGS="$SHARED_CFLAGS -xregs=no%appl" - esac - case $target_os in - solaris2.[89]*|solaris2.1[0-9]*) - LIBR_MANEXT=3lib - FUNC_MANEXT=3tecla - LIBR_MANDIR=man$LIBR_MANEXT - FUNC_MANDIR=man$FUNC_MANEXT - esac - MISC_MANDIR="man5" - MISC_MANEXT="5" - FILE_MANDIR="man4" - FILE_MANEXT="4" - ;; -*linux*) - SHARED_EXT=".so.${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}" - SHARED_ALT=".so .so.${MAJOR_VER}" - - - echo "$as_me:$LINENO: checking for --version-script in GNU ld" >&5 -echo $ECHO_N "checking for --version-script in GNU ld... $ECHO_C" >&6 -if test "${tecla_cv_gnu_ld_script+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&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 "$as_me:$LINENO: result: $tecla_cv_gnu_ld_script" >&5 -echo "${ECHO_T}$tecla_cv_gnu_ld_script" >&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" - - - CFLAGS="-D_SVID_SOURCE -D_BSD_SOURCE $CFLAGS" - ;; -*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" - MISC_MANEXT=5 - FILE_MANEXT=4 - MISC_MANDIR=man$MISC_MANEXT - FILE_MANDIR=man$FILE_MANEXT - ;; -*darwin*) - SHARED_EXT=".${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}.dylib" - SHARED_ALT=".dylib .${MAJOR_VER}.dylib" - LINK_SHARED='$(CC) -o $$@ -dynamiclib -flat_namespace -undefined suppress -compatibility_version '${MAJOR_VER}.${MINOR_VER}' -current_version '${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}' -install_name '${libdir}'/$$@ $$(LIB_OBJECTS)' - SHARED_CFLAGS="" - ;; -*dec-osf*) - cat >>confdefs.h <<\_ACEOF -#define _OSF_SOURCE 1 -_ACEOF - - ;; -*freebsd*) - SHARED_EXT=".so.${MAJOR_VER}" - SHARED_ALT=".so" - VERSION_OPT='--version-script=$$(srcdir)/libtecla.map' - LINK_SHARED='ld -o $$@ -soname libtecla$$(SUFFIX).so.'${MAJOR_VER}' -shared '$VERSION_OPT' $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="-fpic" - ;; -mips-sgi-irix*) - DEFS_R="$DEFS_R -D_XOPEN_SOURCE=500" - if test "$RANLIB"_ = "_"; then - RANLIB=":" - fi - ;; -esac - - -if test "$GCC"_ = "yes"_ && test "$LINK_SHARED"_ != "_" ; then - SHARED_CFLAGS="-fpic" - case $target in - sparc-*-solaris*) - SHARED_CFLAGS="$SHARED_CFLAGS -mno-app-regs" - ;; - *darwin*) - SHARED_CFLAGS="" - ;; - 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 - - - - -# Check whether --with-man-pages or --without-man-pages was given. -if test "${with_man_pages+set}" = set; then - withval="$with_man_pages" - MAKE_MAN_PAGES="$withval" -else - MAKE_MAN_PAGES="yes" -fi; - - -OUTPUT_FILES="Makefile" -rm -rf man/man* -if test "$MAKE_MAN_PAGES"_ = "yes"_; then - for area in libr func misc prog file; do - for page in man/$area/*.in; do - OUTPUT_FILES="$OUTPUT_FILES `echo $page | sed 's/\.in$//'`" - done - done -fi - - - ac_config_files="$ac_config_files $OUTPUT_FILES" -cat >confcache <<\_ACEOF -# 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, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# 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 \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} | - sed ' - t clear - : clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" - cat confcache >$cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then we branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -cat >confdef2opt.sed <<\_ACEOF -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g -t quote -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g -t quote -d -: quote -s,[ `~#$^&*(){}\\|;'"<>?],\\&,g -s,\[,\\&,g -s,\],\\&,g -s,\$,$$,g -p -_ACEOF -# We use echo to avoid assuming a particular line-breaking character. -# The extra dot is to prevent the shell from consuming trailing -# line-breaks from the sub-command output. A line-break within -# single-quotes doesn't work because, if this script is created in a -# platform that uses two characters for line-breaks (e.g., DOS), tr -# would break. -ac_LF_and_DOT=`echo; echo .` -DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` -rm -f confdef2opt.sed - - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi - -# Support unset when possible. -if (FOO=FOO; unset FOO) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - -exec 6>&1 - -# Open the log real soon, to keep \$[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - -This file was extended by $as_me, which was -generated by GNU Autoconf 2.57. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 -_ACEOF - -# Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi - -cat >>$CONFIG_STATUS <<\_ACEOF - -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to <bug-autoconf@gnu.org>." -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.57, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" - -Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` - ac_shift=: - ;; - -*) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; - esac - - case $ac_option in - # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" - ac_need_defaults=false;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF - - - - - -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_config_target in $ac_config_targets -do - case "$ac_config_target" in - # Handling of arguments. - "$OUTPUT_FILES" ) CONFIG_FILES="$CONFIG_FILES $OUTPUT_FILES" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. -$debug || -{ - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF - -# -# CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s,@SHELL@,$SHELL,;t t -s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t -s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t -s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s,@exec_prefix@,$exec_prefix,;t t -s,@prefix@,$prefix,;t t -s,@program_transform_name@,$program_transform_name,;t t -s,@bindir@,$bindir,;t t -s,@sbindir@,$sbindir,;t t -s,@libexecdir@,$libexecdir,;t t -s,@datadir@,$datadir,;t t -s,@sysconfdir@,$sysconfdir,;t t -s,@sharedstatedir@,$sharedstatedir,;t t -s,@localstatedir@,$localstatedir,;t t -s,@libdir@,$libdir,;t t -s,@includedir@,$includedir,;t t -s,@oldincludedir@,$oldincludedir,;t t -s,@infodir@,$infodir,;t t -s,@mandir@,$mandir,;t t -s,@build_alias@,$build_alias,;t t -s,@host_alias@,$host_alias,;t t -s,@target_alias@,$target_alias,;t t -s,@DEFS@,$DEFS,;t t -s,@ECHO_C@,$ECHO_C,;t t -s,@ECHO_N@,$ECHO_N,;t t -s,@ECHO_T@,$ECHO_T,;t t -s,@LIBS@,$LIBS,;t t -s,@MAJOR_VER@,$MAJOR_VER,;t t -s,@MINOR_VER@,$MINOR_VER,;t t -s,@MICRO_VER@,$MICRO_VER,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t -s,@SET_MAKE@,$SET_MAKE,;t t -s,@LN_S@,$LN_S,;t t -s,@AWK@,$AWK,;t t -s,@RANLIB@,$RANLIB,;t t -s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t -s,@LD@,$LD,;t t -s,@ac_ct_LD@,$ac_ct_LD,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t -s,@target@,$target,;t t -s,@target_cpu@,$target_cpu,;t t -s,@target_vendor@,$target_vendor,;t t -s,@target_os@,$target_os,;t t -s,@CPP@,$CPP,;t t -s,@EGREP@,$EGREP,;t t -s,@TARGETS@,$TARGETS,;t t -s,@SHARED_EXT@,$SHARED_EXT,;t t -s,@SHARED_ALT@,$SHARED_ALT,;t t -s,@SHARED_CFLAGS@,$SHARED_CFLAGS,;t t -s,@LINK_SHARED@,$LINK_SHARED,;t t -s,@DEFS_R@,$DEFS_R,;t t -s,@LIBR_MANDIR@,$LIBR_MANDIR,;t t -s,@LIBR_MANEXT@,$LIBR_MANEXT,;t t -s,@FUNC_MANDIR@,$FUNC_MANDIR,;t t -s,@FUNC_MANEXT@,$FUNC_MANEXT,;t t -s,@PROG_MANDIR@,$PROG_MANDIR,;t t -s,@PROG_MANEXT@,$PROG_MANEXT,;t t -s,@MISC_MANDIR@,$MISC_MANDIR,;t t -s,@MISC_MANEXT@,$MISC_MANEXT,;t t -s,@FILE_MANDIR@,$FILE_MANDIR,;t t -s,@FILE_MANEXT@,$FILE_MANEXT,;t t -s,@TARGET_LIBS@,$TARGET_LIBS,;t t -s,@MAKE_MAN_PAGES@,$MAKE_MAN_PAGES,;t t -s,@LIBOBJS@,$LIBOBJS,;t t -s,@LTLIBOBJS@,$LTLIBOBJS,;t t -CEOF - -_ACEOF - - cat >>$CONFIG_STATUS <<\_ACEOF - # 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_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # 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" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat - fi -fi # test -n "$CONFIG_FILES" - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` - - - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo $f;; - *) # Relative - if test -f "$f"; then - # Build tree - echo $f - elif test -f "$srcdir/$f"; then - # Source tree - echo $srcdir/$f - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s,@configure_input@,$configure_input,;t t -s,@srcdir@,$ac_srcdir,;t t -s,@abs_srcdir@,$ac_abs_srcdir,;t t -s,@top_srcdir@,$ac_top_srcdir,;t t -s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s,@builddir@,$ac_builddir,;t t -s,@abs_builddir@,$ac_abs_builddir,;t t -s,@top_builddir@,$ac_top_builddir,;t t -s,@abs_top_builddir@,$ac_abs_top_builddir,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi - -done -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - diff --git a/libtecla-1.6.1/configure.in b/libtecla-1.6.1/configure.in deleted file mode 100644 index 78e7170..0000000 --- a/libtecla-1.6.1/configure.in +++ /dev/null @@ -1,582 +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="6" - -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. -dnl Note that we do not use AC_PROG_RANLIB because (at least in -dnl autoconf 2.53) this does not check for cross-compilation. - -AC_CHECK_TOOL(RANLIB, ranlib) - -dnl Set LD as appropriate, especially when cross-compiling - -AC_CHECK_TOOL(LD, ld) - -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_os in -solaris2.[[0-6]]|solaris2.[[0-6]].*) - LIBS="$LIBS -L/usr/ccs/lib" - ;; -esac - -dnl Recent versions of gcc place /usr/local/include at the head of the -dnl system include-file search path. This causes problems when include -dnl files that have the same name as standard system include files are -dnl placed in this directory by third-party packages. To avoid this, -dnl move /usr/local/include to the end of the search path. - -if test "$GCC"_ = "yes"_; then - touch foo.c - fix=`$CC -E -Wp,-v foo.c 2>&1 | $AWK ' - /^#include <...> search starts here:/ {in_list=1;ndir=0} - / *\// && in_list {path[[ndir++]] = $1} - /^End of search list/ {in_list=0} - END { - if(path[[0]] ~ /\/usr\/local\/include/) { - for(dir=1; dir<ndir; dir++) { - printf(" -isystem %s", path[[dir]]) - } - printf("\n"); - } - }'` - rm -f foo.c - CFLAGS="$CFLAGS$fix" -fi - -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 Search for the curses.h and term.h header files, first in the -dnl standard system-include directories, and then if not found there, -dnl in any ncurses subdirectories of these directories. If found, have -dnl CFLAGS define C macros such as HAVE_TERM_H or HAVE_NCURSES_TERM_H. -dnl Note that on some systems trying to compile term.h without first -dnl including curses.h causes complaints, so when checking for term.h -dnl we tell AC_CHECK_HEADERS() to include curses.h in the test file -dnl that it attempts to compile. - -AC_CHECK_HEADERS(curses.h, [AC_CHECK_HEADERS(term.h,[],[],[#include <curses.h>])], [AC_CHECK_HEADERS(ncurses/curses.h, [AC_CHECK_HEADERS(ncurses/term.h,[],[],[#include <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 If sys/select.h exists, arrange for the HAVE_SYS_SELECT_H C-macro to -dnl be defined when compiling the library. - -AC_CHECK_HEADER(sys/select.h, AC_DEFINE(HAVE_SYS_SELECT_H)) - -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([ -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - ], [ - 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 When compiling the reentrant version of the library, the following -dnl compiler flags are presented to the compiler, in addition to those -dnl that are used when compiling the non-reentrant version of the -dnl library. The PREFER_REENTRANT macro is an internal libtecla macro -dnl whose presence reports when the reentrant version of the library -dnl is being compiled. This allows the code to determine when to -dnl disable features that can't portably be implemented reentrantly, -dnl such as username completion. The existence of the _POSIX_C_SOURCE -dnl macro can't be reliably used for this purpose, since some systems -dnl define it by default for all code. - -AC_SUBST(DEFS_R) -DEFS_R="-D_POSIX_C_SOURCE=199506L -DPREFER_REENTRANT" - -dnl For man pages relating to library features, the following two -dnl variables determine in which sub-directory of the top-level man -dnl directory the man pages should go, and what file-name extensions -dnl these files should have. On systems where the following defaults -dnl are not valid, the default values should be overriden in the -dnl target-specific case statement later in this file. - -AC_SUBST(LIBR_MANDIR) -AC_SUBST(LIBR_MANEXT) -LIBR_MANDIR="man3" -LIBR_MANEXT="3" - -dnl For man pages relating to library functions, the following two -dnl variables serve the same purpose as the previously described -dnl LIBR_MANDIR and LIBR_MANEXT variables. - -AC_SUBST(FUNC_MANDIR) -AC_SUBST(FUNC_MANEXT) -FUNC_MANDIR="man3" -FUNC_MANEXT="3" - -dnl For man pages relating to programs, the following two variables -dnl serve the same purpose as the previously described LIBR_MANDIR -dnl and LIBR_MANEXT variables. - -AC_SUBST(PROG_MANDIR) -AC_SUBST(PROG_MANEXT) -PROG_MANDIR="man1" -PROG_MANEXT="1" - -dnl For man pages on miscellaneous topics, the following two variables -dnl serve the same purpose as the previously described LIBR_MANDIR -dnl and LIBR_MANEXT variables. - -AC_SUBST(MISC_MANDIR) -AC_SUBST(MISC_MANEXT) -MISC_MANDIR="man7" -MISC_MANEXT="7" - -dnl For man pages relating to configuration files, the following two -dnl variables serve the same purpose as the previously described -dnl LIBR_MANDIR and LIBR_MANEXT variables. - -AC_SUBST(FILE_MANDIR) -AC_SUBST(FILE_MANEXT) -FILE_MANDIR="man5" -FILE_MANEXT="5" - -dnl If the application doesn't want the user to have access to the -dnl filesystem, it can remove all action functions that list, read or -dnl write files, by including the configuration argument -dnl --without-file-actions. - -AC_ARG_WITH(file-actions, AC_HELP_STRING([--with-file-actions], [Should users of gl_get_line() have access to the filesystem (default=yes)]), - AC_DEFINE(HIDE_FILE_SYSTEM), ) - -dnl If the target system either has no file-system, or file-system access -dnl isn't needed, libtecla can be made smaller by excluding all file and -dnl directory access code. This is done by adding the configuration -dnl argument --without-file-system. - -AC_ARG_WITH(file-system, AC_HELP_STRING([--with-file-system], [Does the target have a filesystem (default=yes)]), - AC_DEFINE(WITHOUT_FILE_SYSTEM), ) - -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" ;; - esac - case $target_cpu in - sparc) SHARED_CFLAGS="$SHARED_CFLAGS -xregs=no%appl" - esac - case $target_os in - solaris2.[[89]]*|solaris2.1[[0-9]]*) - LIBR_MANEXT=3lib - FUNC_MANEXT=3tecla - LIBR_MANDIR=man$LIBR_MANEXT - FUNC_MANDIR=man$FUNC_MANEXT - esac - MISC_MANDIR="man5" - MISC_MANEXT="5" - FILE_MANDIR="man4" - FILE_MANEXT="4" - ;; -*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" - -dnl Reenable the inclusion of symbols which get undefined when POSIX_C_SOURCE -dnl is specified. - - CFLAGS="-D_SVID_SOURCE -D_BSD_SOURCE $CFLAGS" - ;; -*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" - MISC_MANEXT=5 - FILE_MANEXT=4 - MISC_MANDIR=man$MISC_MANEXT - FILE_MANDIR=man$FILE_MANEXT - ;; -*darwin*) - SHARED_EXT=".${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}.dylib" - SHARED_ALT=".dylib .${MAJOR_VER}.dylib" - LINK_SHARED='$(CC) -o $$@ -dynamiclib -flat_namespace -undefined suppress -compatibility_version '${MAJOR_VER}.${MINOR_VER}' -current_version '${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}' -install_name '${libdir}'/$$@ $$(LIB_OBJECTS)' - SHARED_CFLAGS="" - ;; -*dec-osf*) - AC_DEFINE(_OSF_SOURCE) - ;; -*freebsd*) - SHARED_EXT=".so.${MAJOR_VER}" - SHARED_ALT=".so" - VERSION_OPT='--version-script=$$(srcdir)/libtecla.map' - LINK_SHARED='ld -o $$@ -soname libtecla$$(SUFFIX).so.'${MAJOR_VER}' -shared '$VERSION_OPT' $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="-fpic" - ;; -mips-sgi-irix*) - DEFS_R="$DEFS_R -D_XOPEN_SOURCE=500" - if test "$RANLIB"_ = "_"; then - RANLIB=":" - fi - ;; -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 in - sparc-*-solaris*) - SHARED_CFLAGS="$SHARED_CFLAGS -mno-app-regs" - ;; - *darwin*) - SHARED_CFLAGS="" - ;; - 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 Set the shell variable and Makefile variable, MAKE_MAN_PAGES, to -dnl "yes" if man pages are desired. By default they are, but if the -dnl user specifies --with-man-pages=no or --without-man-pages, then -dnl they won't be preprocessed by the configure script or installed -dnl by the Makefile. - -AC_SUBST(MAKE_MAN_PAGES) -AC_ARG_WITH(man-pages, AC_HELP_STRING([--with-man-pages], [Are man pages desired (default=yes)]), - MAKE_MAN_PAGES="$withval", MAKE_MAN_PAGES="yes") - -dnl Create the list of files to be generated by the configure script. - -OUTPUT_FILES="Makefile" -rm -rf man/man* -if test "$MAKE_MAN_PAGES"_ = "yes"_; then - for area in libr func misc prog file; do - for page in man/$area/*.in; do - OUTPUT_FILES="$OUTPUT_FILES `echo $page | sed 's/\.in$//'`" - done - done -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($OUTPUT_FILES) diff --git a/libtecla-1.6.1/cplfile.c b/libtecla-1.6.1/cplfile.c deleted file mode 100644 index eee3166..0000000 --- a/libtecla-1.6.1/cplfile.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/* - * If file-system access is to be excluded, this module has no function, - * so all of its code should be excluded. - */ -#ifndef WITHOUT_FILE_SYSTEM - -/* - * 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" -#include "errmsg.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 - -/* - * The resources needed to complete a filename are maintained in objects - * of the following type. - */ -struct CompleteFile { - ErrMsg *err; /* The error reporting buffer */ - 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. */ -}; - -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 */ - size_t prefix_len; /* The length of the prefix being 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) { - errno = ENOMEM; - 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->err = NULL; - cf->dr = NULL; - cf->home = NULL; - cf->path = NULL; - cf->buff = NULL; - cf->usrnam[0] = '\0'; - cf->envnam[0] = '\0'; -/* - * Allocate a place to record error messages. - */ - cf->err = _new_ErrMsg(); - if(!cf->err) - return _del_CompleteFile(cf); -/* - * 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->err = _del_ErrMsg(cf->err); - 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) { - _err_record_msg(cf->err, "_cf_complete_file: Invalid arguments", - END_ERR_MSG); - }; - 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) { - _err_record_msg(cf->err, "Insufficient memory to complete filename", - END_ERR_MSG); - 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) { - _err_record_msg(cf->err, "Unknown environment variable: ", cf->envnam, - END_ERR_MSG); - 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) { - _err_record_msg(cf->err, "Insufficient memory to complete filename", - END_ERR_MSG); - 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, - "", "")) { - _err_record_msg(cf->err, cpl_last_error(cpl), END_ERR_MSG); - 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 ? _err_get_msg(cf->err) : "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) { - _err_record_msg(cf->err, _hd_last_home_dir_error(cf->home), END_ERR_MSG); - return 1; - }; -/* - * Append the home directory to the pathname string. - */ - if(_pn_append_to_path(cf->path, home_dir, -1, 0) == NULL) { - _err_record_msg(cf->err, "Insufficient memory for home directory expansion", - END_ERR_MSG); - 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_len = strlen(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, prefix, &args, cf_homedir_callback)) { - _err_record_msg(cf->err, _hd_last_home_dir_error(cf->home), END_ERR_MSG); - 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; -/* - * Copy the username into the pathname work buffer, adding backslash - * escapes where needed. - */ - if(cf_prepare_suffix(cf, usrnam+args->prefix_len, args->escaped)) { - strncpy(errmsg, _err_get_msg(cf->err), 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)) { - _err_record_msg(cf->err, "Can't open directory: ", dirpath, END_ERR_MSG); - 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) { - _err_record_msg(cf->err, - "Insufficient memory to complete filename.", - END_ERR_MSG); - 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->err. - */ -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) { - _err_record_msg(cf->err, type, " name too long", END_ERR_MSG); - 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) { - _err_record_msg(cf->err, "Insufficient memory to complete filename", - END_ERR_MSG); - 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; -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/cplfile.h b/libtecla-1.6.1/cplfile.h deleted file mode 100644 index a7ca9fb..0000000 --- a/libtecla-1.6.1/cplfile.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef cplfile_h -#define cplfile_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/cplmatch.c b/libtecla-1.6.1/cplmatch.c deleted file mode 100644 index ece93d3..0000000 --- a/libtecla-1.6.1/cplmatch.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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> -#include <errno.h> - -/* - * Local includes. - */ -#include "libtecla.h" -#include "ioutil.h" -#include "stringrp.h" -#include "pathutil.h" -#include "cplfile.h" -#include "cplmatch.h" -#include "errmsg.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 default number of spaces place between columns when listing - * a set of completions. - */ -#define CPL_COL_SEP 2 - -/* - * Completion matches are recorded in containers of the following - * type. - */ -struct WordCompletion { - ErrMsg *err; /* The error reporting buffer */ - StringGroup *sg; /* Memory for a group of strings */ - int matches_dim; /* The allocated size of result.matches[] */ - CplMatches result; /* Completions to be returned to the caller */ -#ifndef WITHOUT_FILE_SYSTEM - CompleteFile *cf; /* The resources used for filename completion */ -#endif -}; - -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 - -#ifndef WITHOUT_FILE_SYSTEM -/* - * 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); - -/* - * When file-system access is being excluded, define a dummy structure - * to satisfy the typedef in libtecla.h. - */ -#else -struct CplFileConf {int dummy;}; -#endif - -/* - * Encapsulate the formatting information needed to layout a - * multi-column listing of completions. - */ -typedef struct { - int term_width; /* The width of the terminal (characters) */ - int column_width; /* The number of characters within in each column. */ - int ncol; /* The number of columns needed */ - int nline; /* The number of lines needed */ -} CplListFormat; - -/* - * Given the current terminal width, and a list of completions, determine - * how to best use the terminal width to display a multi-column listing - * of completions. - */ -static void cpl_plan_listing(CplMatches *result, int term_width, - CplListFormat *fmt); - -/* - * Display a given line of a multi-column list of completions. - */ -static int cpl_format_line(CplMatches *result, CplListFormat *fmt, int lnum, - GlWriteFn *write_fn, void *data); - -/*....................................................................... - * 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) { - errno = ENOMEM; - 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->err = NULL; - cpl->sg = NULL; - cpl->matches_dim = 0; - cpl->result.suffix = NULL; - cpl->result.cont_suffix = NULL; - cpl->result.matches = NULL; - cpl->result.nmatch = 0; -#ifndef WITHOUT_FILE_SYSTEM - cpl->cf = NULL; -#endif -/* - * Allocate a place to record error messages. - */ - cpl->err = _new_ErrMsg(); - if(!cpl->err) - return del_WordCompletion(cpl); -/* - * Allocate an object that allows a group of strings to be allocated - * efficiently by placing many of them in contiguous string segments. - */ -#ifdef WITHOUT_FILE_SYSTEM - cpl->sg = _new_StringGroup(MAX_PATHLEN_FALLBACK); -#else - cpl->sg = _new_StringGroup(_pu_pathname_dim()); -#endif - 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) { - errno = ENOMEM; - return del_WordCompletion(cpl); - }; -/* - * Allocate a filename-completion resource object. - */ -#ifndef WITHOUT_FILE_SYSTEM - cpl->cf = _new_CompleteFile(); - if(!cpl->cf) - return del_WordCompletion(cpl); -#endif - 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->err = _del_ErrMsg(cpl->err); - cpl->sg = _del_StringGroup(cpl->sg); - if(cpl->result.matches) { - free(cpl->result.matches); - cpl->result.matches = NULL; -#ifndef WITHOUT_FILE_SYSTEM - cpl->cf = _del_CompleteFile(cpl->cf); -#endif - }; - 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) { - _err_record_msg(cpl->err, - "Insufficient memory to extend array of matches.", - END_ERR_MSG); - 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) { - _err_record_msg(cpl->err, "Insufficient memory to extend array of matches.", - END_ERR_MSG); - 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) { - _err_record_msg(cpl->err, - "Insufficient memory to record common completion suffix.", - END_ERR_MSG); - 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. - */ - _err_clear_msg(cpl->err); - 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) { - _err_record_msg(cpl->err, "cpl_complete_word: Invalid arguments.", - END_ERR_MSG); - }; - 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(_err_get_msg(cpl->err)[0] == '\0') - _err_record_msg(cpl->err, "Error completing word.", END_ERR_MSG); - 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; -} - -/*....................................................................... - * Recall the return value of the last call to cpl_complete_word(). - * - * Input: - * cpl WordCompletion * The completion resource object. - * Output: - * return CplMatches * The container of the array of possible - * completions, as returned by the last call to - * cpl_complete_word(). The returned pointer refers - * to a container owned by the parent WordCompletion - * object, and its contents thus potentially - * change on every call to cpl_complete_word(). - * On error, either in the execution of this - * function, or in the last call to - * cpl_complete_word(), NULL is returned, and a - * description of the error can be acquired by - * calling cpl_last_error(cpl). - */ -CplMatches *cpl_recall_matches(WordCompletion *cpl) -{ - return (!cpl || *_err_get_msg(cpl->err)!='\0') ? NULL : &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) -{ - return _cpl_output_completions(result, _io_write_stdio, fp, term_width); -} - -/*....................................................................... - * Print an array of matching completions via a callback function. - * - * Input: - * result CplMatches * The container of the sorted array of - * completions. - * write_fn GlWriteFn * The function to call to write the completions, - * or 0 to discard the output. - * data void * Anonymous data to pass to write_fn(). - * term_width int The width of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _cpl_output_completions(CplMatches *result, GlWriteFn *write_fn, void *data, - int term_width) -{ - CplListFormat fmt; /* List formatting information */ - int lnum; /* The sequential number of the line to print next */ -/* - * Not enough space to list anything? - */ - if(term_width < 1) - return 0; -/* - * Do we have a callback to write via, and any completions to be listed? - */ - if(write_fn && result && result->nmatch>0) { -/* - * Work out how to arrange the listing into fixed sized columns. - */ - cpl_plan_listing(result, term_width, &fmt); -/* - * Print the listing via the specified callback. - */ - for(lnum=0; lnum < fmt.nline; lnum++) { - if(cpl_format_line(result, &fmt, lnum, write_fn, data)) - return 1; - }; - }; - 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 ? _err_get_msg(cpl->err) : "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) - _err_record_msg(cpl->err, errmsg, END_ERR_MSG); -} - -/*....................................................................... - * 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) -{ -#ifdef WITHOUT_FILE_SYSTEM - return 0; -#else - 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) { - _err_record_msg(cpl->err, "cpl_file_completions: Invalid arguments.", - END_ERR_MSG); - 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) { - _err_record_msg(cpl->err, "Unable to find the start of the filename.", - END_ERR_MSG); - 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; -#endif -} - -/*....................................................................... - * 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; - }; -} - -#ifndef WITHOUT_FILE_SYSTEM -/*....................................................................... - * 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; - }; -} -#endif - -/*....................................................................... - * Create a new CplFileConf object and initialize it with defaults. - * - * Output: - * return CplFileConf * The new object, or NULL on error. - */ -CplFileConf *new_CplFileConf(void) -{ -#ifdef WITHOUT_FILE_SYSTEM - errno = EINVAL; - return NULL; -#else - 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; -#endif -} - -/*....................................................................... - * 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) -{ -#ifndef WITHOUT_FILE_SYSTEM - if(cfc) { -/* - * Delete the container. - */ - free(cfc); - }; -#endif - 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) -{ -#ifndef WITHOUT_FILE_SYSTEM - if(cfc) - cfc->escaped = !literal; -#endif -} - -/*....................................................................... - * 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) -{ -#ifndef WITHOUT_FILE_SYSTEM - if(cfc) - cfc->file_start = start_index; -#endif -} - -/*....................................................................... - * 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) -{ -#ifndef WITHOUT_FILE_SYSTEM - if(cfc) { - cfc->chk_fn = chk_fn; - cfc->chk_data = chk_data; - }; -#endif -} - -/*....................................................................... - * The following CplCheckFn callback returns non-zero if the specified - * filename is that of an executable. - */ -CPL_CHECK_FN(cpl_check_exe) -{ -#ifdef WITHOUT_FILE_SYSTEM - return 0; -#else - return _pu_path_is_exe(pathname); -#endif -} - -/*....................................................................... - * 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; -} - -/*....................................................................... - * Work out how to arrange a given array of completions into a listing - * of one or more fixed size columns. - * - * Input: - * result CplMatches * The set of completions to be listed. - * term_width int The width of the terminal. A lower limit of - * zero is quietly enforced. - * Input/Output: - * fmt CplListFormat * The formatting information will be assigned - * to the members of *fmt. - */ -static void cpl_plan_listing(CplMatches *result, int term_width, - CplListFormat *fmt) -{ - int maxlen; /* The length of the longest matching string */ - int i; -/* - * Ensure that term_width >= 0. - */ - if(term_width < 0) - term_width = 0; -/* - * Start by assuming the worst case, that either nothing will fit - * on the screen, or that there are no matches to be listed. - */ - fmt->term_width = term_width; - fmt->column_width = 0; - fmt->nline = fmt->ncol = 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; -/* - * Split the available terminal width into columns of - * maxlen + CPL_COL_SEP characters. - */ - fmt->column_width = maxlen; - fmt->ncol = fmt->term_width / (fmt->column_width + CPL_COL_SEP); -/* - * If the column width is greater than the terminal width, zero columns - * will have been selected. Set a lower limit of one column. Leave it - * up to the caller how to deal with completions who's widths exceed - * the available terminal width. - */ - if(fmt->ncol < 1) - fmt->ncol = 1; -/* - * How many lines of output will be needed? - */ - fmt->nline = (result->nmatch + fmt->ncol - 1) / fmt->ncol; - return; -} - -/*....................................................................... - * Render one line of a multi-column listing of completions, using a - * callback function to pass the output to an arbitrary destination. - * - * Input: - * result CplMatches * The container of the sorted array of - * completions. - * fmt CplListFormat * Formatting information. - * lnum int The index of the line to print, starting - * from 0, and incrementing until the return - * value indicates that there is nothing more - * to be printed. - * write_fn GlWriteFn * The function to call to write the line, or - * 0 to discard the output. - * data void * Anonymous data to pass to write_fn(). - * Output: - * return int 0 - Line printed ok. - * 1 - Nothing to print. - */ -static int cpl_format_line(CplMatches *result, CplListFormat *fmt, int lnum, - GlWriteFn *write_fn, void *data) -{ - int col; /* The index of the list column being output */ -/* - * If the line index is out of bounds, there is nothing to be written. - */ - if(lnum < 0 || lnum >= fmt->nline) - return 1; -/* - * If no output function has been provided, return as though the - * line had been printed. - */ - if(!write_fn) - return 0; -/* - * Print the matches in 'ncol' columns, sorted in line order within each - * column. - */ - for(col=0; col < fmt->ncol; col++) { - int m = col*fmt->nline + lnum; -/* - * Is there another match to be written? Note that in general - * the last line of a listing will have fewer filled columns - * than the initial lines. - */ - if(m < result->nmatch) { - CplMatch *match = result->matches + m; -/* - * How long are the completion and type-suffix strings? - */ - int clen = strlen(match->completion); - int tlen = strlen(match->type_suffix); -/* - * Write the completion string. - */ - if(write_fn(data, match->completion, clen) != clen) - return 1; -/* - * Write the type suffix, if any. - */ - if(tlen > 0 && write_fn(data, match->type_suffix, tlen) != tlen) - return 1; -/* - * If another column follows the current one, pad to its start with spaces. - */ - if(col+1 < fmt->ncol) { -/* - * The following constant string of spaces is used to pad the output. - */ - static const char spaces[] = " "; - static const int nspace = sizeof(spaces) - 1; -/* - * Pad to the next column, using as few sub-strings of the spaces[] - * array as possible. - */ - int npad = fmt->column_width + CPL_COL_SEP - clen - tlen; - while(npad>0) { - int n = npad > nspace ? nspace : npad; - if(write_fn(data, spaces + nspace - n, n) != n) - return 1; - npad -= n; - }; - }; - }; - }; -/* - * Start a new line. - */ - { - char s[] = "\r\n"; - int n = strlen(s); - if(write_fn(data, s, n) != n) - return 1; - }; - return 0; -} diff --git a/libtecla-1.6.1/cplmatch.h b/libtecla-1.6.1/cplmatch.h deleted file mode 100644 index cb50006..0000000 --- a/libtecla-1.6.1/cplmatch.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef cplmatch_h -#define cplmatch_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 header is not for use by external applicatons. It contains - * internal immplementation features of the libtecla library, which - * may change incompatibly between releases. - */ - -/* - * Display a list of completions via a callback function. - */ -int _cpl_output_completions(CplMatches *result, GlWriteFn *write_fn, void *data, - int term_width); - -#endif diff --git a/libtecla-1.6.1/demo.c b/libtecla-1.6.1/demo.c deleted file mode 100644 index d29b11a..0000000 --- a/libtecla-1.6.1/demo.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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" - -/* The function which displays the introductory text of the demo */ - -static void show_demo_introduction(GetLine *gl); - -/*....................................................................... - * This program demonstrates how to use gl_get_line() as a line editor to - * to enable users to enter input. It takes no arguments. - */ -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("\n Welcome to the main demo program of libtecla version %d.%d.%d\n", - major, minor, micro); -/* - * Display an introductory banner. - */ - show_demo_introduction(gl); -/* - * Load history. - */ -#ifndef WITHOUT_FILE_SYSTEM - (void) gl_load_history(gl, "~/.demo_history", "#"); -#endif -/* - * 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); - } else if(strcmp(line, "clear\n")==0) { - if(gl_erase_terminal(gl)) - return 1; - }; - } while(1); -/* - * Save historical command lines. - */ -#ifndef WITHOUT_FILE_SYSTEM - (void) gl_save_history(gl, "~/.demo_history", "#", -1); -#endif -/* - * Clean up. - */ - gl = del_GetLine(gl); - return 0; -} - -/*....................................................................... - * Display introductory text to the user, formatted according to the - * current terminal width and enclosed in a box of asterixes. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -static void show_demo_introduction(GetLine *gl) -{ - int start; /* The column in which gl_display_text() left the cursor */ - int i; -/* - * Break the indtroductory text into an array of strings, so as to - * avoid overflowing any compiler string limits. - */ - const char *doc[] = { - "This program is a simple shell with which you can experiment with the ", - "line editing and tab completion facilities provided by the gl_get_line() ", - "function. The file demo.c also serves as a fully commented example ", - "of how to use gl_get_line().\n" - }; -/* - * Form the top line of the documentation box by filling the area of - * the line between a " *" prefix and a "* " suffix with asterixes. - */ - printf("\n"); - gl_display_text(gl, 0, " *", "* ", '*', 80, 0, "\n"); -/* - * Justify the documentation text within margins of asterixes. - */ - for(start=0,i=0; i<sizeof(doc)/sizeof(doc[0]) && start >= 0; i++) - start = gl_display_text(gl, 0, " * ", " * ", ' ', 80, start,doc[i]); -/* - * Draw the bottom line of the documentation box. - */ - gl_display_text(gl, 0, " *", "* ", '*', 80, 0, "\n"); - printf("\n"); -} diff --git a/libtecla-1.6.1/demo2.c b/libtecla-1.6.1/demo2.c deleted file mode 100644 index 63a9a0c..0000000 --- a/libtecla-1.6.1/demo2.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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" - -/* - * If the library is being built with file-system access excluded, this - * demo program won't have anything to demonstrate. - */ -#ifdef WITHOUT_FILE_SYSTEM -int main(int argc, char *argv[]) -{ - fprintf(stderr, "\n" - " This program normally demonstrates tecla's path-lookup\n" - " facility. However libtecla has been installed with\n" - " file-system facilities explicitly excluded, so there is\n" - " nothing to demonstrate.\n\n"); - return 1; -} -#else -/* - * 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); - -/* The function which displays the introductory text of the demo */ - -static void show_demo_introduction(GetLine *gl); - -/*....................................................................... - * 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("\n Welcome to the path-search demo of libtecla version %d.%d.%d\n", - major, minor, micro); -/* - * Display some introductory text, left-justifying it within the current - * width of the terminal and enclosing it in a box of asterixes. - */ - show_demo_introduction(res->gl); -/* - * 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; -} - -/*....................................................................... - * Display introductory text to the user, formatted according to the - * current terminal width and enclosed in a box of asterixes. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -static void show_demo_introduction(GetLine *gl) -{ - int start; /* The column in which gl_display_text() left the cursor */ - int i; -/* - * Break the indtroductory text into an array of strings, so as to - * avoid overflowing any compiler string limits. - */ - const char *doc[] = { - "This program demonstrates the use of the pca_lookup_file() function ", - "for finding executables in the UNIX PATH. It also demonstrates ", - "tab completion of the names of executables found in the path. For ", - "example, if you type:\n\n ta\n\nthen hit the tab key, you will be ", - "presented with a list of executables such as tar and tail whose names ", - "start with the string \"ta\". If you decide to add an \"r\" to select ", - "the tar command, then you type return, the full pathname of the tar ", - "program will be printed.\n\nThe file demo2.c contains the code ", - "of this program, and is fully commented to enable its use as ", - "a working example of how to use the facilities documented in the ", - "pca_lookup_file man page.\n"}; -/* - * Form the top line of the documentation box by filling the area of - * the line between a " *" prefix and a "* " suffix with asterixes. - */ - printf("\n"); - gl_display_text(gl, 0, " *", "* ", '*', 80, 0, "\n"); -/* - * Justify the documentation text within margins of asterixes. - */ - for(start=0,i=0; i<sizeof(doc)/sizeof(doc[0]) && start >= 0; i++) - start = gl_display_text(gl, 0, " * ", " * ", ' ', 80, start,doc[i]); -/* - * Draw the bottom line of the documentation box. - */ - gl_display_text(gl, 0, " *", "* ", '*', 80, 0, "\n"); - printf("\n"); -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/demo3.c b/libtecla-1.6.1/demo3.c deleted file mode 100644 index aa204d0..0000000 --- a/libtecla-1.6.1/demo3.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * Copyright (c) 2002, 2003, 2004 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 <setjmp.h> - -#ifdef HAVE_SELECT -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif -#endif - -#include <unistd.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <signal.h> - -#include "libtecla.h" - -/* - * The SignalActions object provides a way to temporarily install - * a signal handler to a given set of signals, and later restore all - * of the signal handlers that this displaced. - */ -typedef struct { - int nsignal; /* The number of signals on the host OS */ - sigset_t mask; /* The set of signals who's signal handlers */ - /* are stored in the following actions[] */ - /* array. */ - struct sigaction *actions; /* An array of nsignal actions */ -} SignalActions; - -static SignalActions *new_SignalActions(void); -static SignalActions *del_SignalActions(SignalActions *si); -static int displace_signal_handlers(SignalActions *si, sigset_t *mask, - void (*handler)(int)); -static int reinstate_signal_handlers(SignalActions *si); - -/* Return resources, restore the terminal to a usable state and exit */ - -static void cleanup_and_exit(GetLine *gl, SignalActions *si, int status); - -/* The function which displays the introductory text of the demo */ - -static void show_demo_introduction(GetLine *gl); - -/* A signal-aware version of select() */ - -static int demo_sigselect(int n, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout, - sigset_t *mask, SignalActions *si); - -/* - * The following variables are accessed from signal handlers. Note - * that these variables don't need to be either volatile or - * sig_atomic_t because: - * - * 1. Outside of signal handlers we only access them when signal - * delivery is blocked, so we know that no signal handlers can - * be accessing them at that time. - * - * 2. When the signal handlers that set these variables are installed, - * the sa_mask member of the sigaction structure is used to ensure - * that only one instance of these signal handlers can be running - * at a time, so we also know that there can't be simultaneous - * accesses to them by multiple signal handlers. - */ -static GetLine *demo_gl; /* The line editor object */ -static sigjmp_buf demo_setjmp_buffer; /* The sigsetjmp() buffer */ -static int demo_setjmp_signo = -1; /* The signal that was caught */ - -/* Signal handlers */ - -static void demo_signal_handler(int signo); -static void demo_setjmp_handler(int signo); - -/* - * Set the amount of time that gl_get_line() should wait for I/O before - * returning to let the external event loop continue. - */ -#define DEMO_IO_TIMEOUT 100000000 /* ns => 100ms */ - -/* The timeout handler */ - -static GL_TIMEOUT_FN(demo_timeout_fn); - -/*....................................................................... - * This program demonstrates the use of gl_get_line() from an external - * event loop. It takes no arguments. - */ -int main(int argc, char *argv[]) -{ - int major,minor,micro; /* The version number of the library */ - GetLine *gl=NULL; /* The resource object of gl_get_line() */ - SignalActions *si=NULL; /* Temporary storage of displaced signal */ - /* handlers. */ - sigset_t all_signal_mask; /* The set of signals known by gl_get_line() */ -/* - * This program requires select(). - */ -#if !defined(HAVE_SELECT) - fprintf(stderr, "The select() system call isn't available - aborting.\n"); - exit(1); -#else -/* - * Create the line editor, specifying a maximum line length of 500 bytes, - * and 10000 bytes to allocate to storage of historical input lines. - */ - gl = demo_gl = new_GetLine(500, 5000); - if(!gl) - cleanup_and_exit(gl, si, 1); - -/* - * Allocate an object in which to temporarily record displaced - * signal handlers. - */ - si = new_SignalActions(); - if(!si) - cleanup_and_exit(gl, si, 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( - "\n Welcome to the server-mode demo program of libtecla version %d.%d.%d\n", - major, minor, micro); -/* - * Display some introductory text, left-justifying it within the current - * width of the terminal and enclosing it in a box of asterixes. - */ - show_demo_introduction(gl); -/* - * Load history. - */ -#ifndef WITHOUT_FILE_SYSTEM - (void) gl_load_history(gl, "~/.demo_history", "#"); -#endif -/* - * In this demo, rather than having gl_get_line() return immediately - * when it would otherwise have to wait for I/O, we register a timeout - * callback which causes gl_get_line() to give up waiting after a short - * interval. - */ - gl_inactivity_timeout(gl, demo_timeout_fn, NULL, 0, DEMO_IO_TIMEOUT); -/* - * Install our signal handlers for process termination, suspension and - * terminal resize signals. Ignore process continuation signals. - */ - gl_tty_signals(demo_signal_handler, demo_signal_handler, SIG_DFL, - demo_signal_handler); -/* - * Get a list of all of the signals that gl_get_line() currently catches. - */ - gl_list_signals(gl, &all_signal_mask); -/* - * Switch gl_get_line() to non-blocking server mode. - */ - if(gl_io_mode(gl, GL_SERVER_MODE)) - cleanup_and_exit(gl, si, 1); -/* - * Instruct gl_get_line() to unblock any signals that it catches - * while waiting for input. Note that in non-blocking server mode, - * this is only necessary when using gl_inactivity_timeout() to make - * gl_get_line() block for a non-zero amount of time. - */ - gl_catch_blocked(gl); -/* - * Enter the event loop. - */ - while(1) { - int nready; /* The number of file-descriptors that are */ - /* ready for I/O */ - fd_set rfds; /* The set of file descriptors to watch for */ - /* readability */ - fd_set wfds; /* The set of file descriptors to watch for */ - /* writability */ -/* - * Construct the sets of file descriptors to be watched by select(), - * starting from empty sets. - */ - FD_ZERO(&rfds); - FD_ZERO(&wfds); -/* - * To ensure that no signals are received whos handlers might change - * the requirements for the contents of the above signal sets, block - * all of the signals that we are handling. - */ - sigprocmask(SIG_BLOCK, &all_signal_mask, NULL); -/* - * Depending on which direction of I/O gl_get_line()s is currently - * waiting for, add the terminal file descriptor to either the set - * of file descriptors to watch for readability, or those to watch - * for writability. Note that at the start of a new line, such as - * after an error, or the return of a completed line, we need to - * wait for writability, so that a prompt can be written. - */ - switch(gl_pending_io(gl)) { - case GLP_READ: - FD_SET(STDIN_FILENO, &rfds); - break; - default: - FD_SET(STDIN_FILENO, &wfds); - break; - }; -/* - * Wait for I/O to become possible on the selected file descriptors. - * The following is a signal-aware wrapper around the select() system - * call. This wrapper guarantees that if any of the signals marked in - * all_signal_mask arrive after the statement above where we blocked - * these signals, it will detect this and abort with nready=-1 and - * errno=EINTR. If instead, we just unblocked the above signals just - * before calling a normal call to select(), there would be a small - * window of time between those two statements in which a signal could - * arrive without aborting select(). This would be a problem, since - * the functions called by our signal handler may change the type - * of I/O that gl_get_line() wants us to wait for in select(). - */ - nready = demo_sigselect(STDIN_FILENO + 1, &rfds, &wfds, NULL, NULL, - &all_signal_mask, si); -/* - * We can now unblock our signals again. - */ - sigprocmask(SIG_UNBLOCK, &all_signal_mask, NULL); -/* - * Did an I/O error occur? - */ - if(nready < 0 && errno != EINTR) - cleanup_and_exit(gl, si, 1); -/* - * If the terminal file descriptor is now ready for I/O, call - * gl_get_line() to continue editing the current input line. - */ - if(FD_ISSET(STDIN_FILENO, &rfds) || FD_ISSET(STDIN_FILENO, &wfds)) { -/* - * Start or continue editing an input line. - */ - char *line = gl_get_line(gl, "$ ", NULL, 0); -/* - * Did the user finish entering a new line? - */ - if(line) { -/* - * Before writing messages to the terminal, start a new line and - * switch back to normal terminal I/O. - */ - gl_normal_io(gl); -/* - * Display what was entered. - */ - if(printf("You entered: %s", line) < 0 || fflush(stdout)) - break; -/* - * Implement a few simple commands. - */ - if(strcmp(line, "exit\n")==0) - cleanup_and_exit(gl, si, 0); - 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); - } else if(strcmp(line, "clear\n")==0) { - if(gl_erase_terminal(gl)) - return 1; - }; -/* - * To resume command-line editing, return the terminal to raw, - * non-blocking I/O mode. - */ - gl_raw_io(gl); -/* - * If gl_get_line() returned NULL because of an error or end-of-file, - * abort the program. - */ - } else if(gl_return_status(gl) == GLR_ERROR || - gl_return_status(gl) == GLR_EOF) { - cleanup_and_exit(gl, si, 1); - }; - }; - }; -#endif - return 0; -} - -/*....................................................................... - * This function is called to return resources to the system and restore - * the terminal to its original state before exiting the process. - * - * Input: - * gl GetLine * The line editor. - * si SignalActions * The repository for displaced signal handlers. - * status int The exit code of the process. - */ -static void cleanup_and_exit(GetLine *gl, SignalActions *si, int status) -{ -/* - * Restore the terminal to its original state before exiting the program. - */ - gl_normal_io(gl); -/* - * Save historical command lines. - */ -#ifndef WITHOUT_FILE_SYSTEM - (void) gl_save_history(gl, "~/.demo_history", "#", -1); -#endif -/* - * Clean up. - */ - gl = del_GetLine(gl); - si = del_SignalActions(si); -/* - * Exit the process. - */ - exit(status); -} - -/*....................................................................... - * This is a signal-aware wrapper around the select() system call. It - * is designed to facilitate reliable signal handling of a given set - * of signals, without the race conditions that would usually surround - * the use of select(). See the "RELIABLE SIGNAL HANDLING" section of - * the gl_get_line(3) man page for further details. - * - * Provided that the calling function has blocked the specified set of - * signals before calling this function, this function guarantees that - * select() will be aborted by any signal that arrives between the - * time that the caller blocked the specified signals and this - * function returns. On return these signals will again be blocked to - * prevent any signals that arrive after select() returns, from being - * missed by the caller. - * - * Note that this function is written not to be specific to this - * program, and is thus suitable for use in other programs, whether or - * not they use gl_get_line(). - * - * Also note that this function depends on the NSIG preprocessor - * constant being >= the maximum number of signals available on the - * host operating system. Under BSD and SysV, this macro is set - * appropriately in signal.h. On other systems, a reasonably large - * guess should be substituted. Although nothing terrible will happen - * if a value that is too small is chosen, signal numbers that exceed - * the specified value of NSIG will be ignored by this function. A - * more robust method than depending on nsig would be to use the - * POSIX sigismember() function to count valid signals, and use this - * to allocate the array of sigaction structures used to preserve - * - * - * Input: - * n int The number of file descriptors to pay - * attention to at the start of each of the - * following sets of file descriptors. - * readfds fd_set * The set of file descriptors to check for - * readability, or NULL if not pertinent. - * wwritefds fd_set * The set of file descriptors to check for - * writability, or NULL if not pertinent. - * exceptfds fd_set * The set of file descriptors to check for - * the arrival of urgent data, or NULL if - * not pertinent. - * timeout struct timeval * The maximum time that select() should - * wait, or NULL to wait forever. - * mask sigset_t * The set of signals to catch. - * si SignalHandlers * An object in which to preserve temporary - * copies signal handlers. - * Output: - * return int > 0 The number of entries in all of the - * sets of descriptors that are ready - * for I/O. - * 0 Select() timed out. - * -1 Error (see errno). - */ -static int demo_sigselect(int n, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout, - sigset_t *mask, SignalActions *si) -{ -/* - * The reason that the the following variables are marked as volatile - * is to prevent the compiler from placing their values in registers - * that might not be saved and restored by sigsetjmp(). - */ - volatile sigset_t old_mask; /* The displaced process signal mask */ - volatile int status; /* The return value of select() */ -/* - * Make sure that all of the specified signals are blocked. This is - * redundant if the caller has already blocked signals. - */ - if(sigprocmask(SIG_BLOCK, mask, (sigset_t *) &old_mask) < 0) - return -1; -/* - * Record the fact that no signal has been caught yet. - */ - demo_setjmp_signo = -1; -/* - * Now set up the point where our temporary signal handlers will return - * control if a signal is received. - */ - if(sigsetjmp(demo_setjmp_buffer, 1) == 0) { -/* - * Now install the temporary signal handlers that cause the above - * sigsetjmp() to return non-zero when a signal is detected. - */ - if(displace_signal_handlers(si, mask, demo_setjmp_handler)) { - reinstate_signal_handlers(si); - return 1; - }; -/* - * Now that we are ready to catch the signals, unblock them. - */ - sigprocmask(SIG_UNBLOCK, mask, NULL); -/* - * At last, call select(). - */ - status = select(n, readfds, writefds, exceptfds, timeout); -/* - * Block the specified signals again. - */ - sigprocmask(SIG_BLOCK, mask, NULL); -/* - * Record the fact that no signal was caught. - */ - demo_setjmp_signo = -1; - }; -/* - * We can get to this point in one of two ways. Either no signals were - * caught, and the above block ran to completion (with demo_setjmp_signo=-1), - * or a signal was caught that caused the above block to be aborted, - * in which case demo_setjmp_signo will now equal the number of the signal that - * was caught, and sigsetjmp() will have restored the process signal - * mask to how it was before it was called (ie. all of the specified - * signals blocked). - * - * First restore the signal handlers to how they were on entry to - * this function. - */ - reinstate_signal_handlers(si); -/* - * Was a signal caught? - */ - if(demo_setjmp_signo > 0) { - sigset_t new_mask; -/* - * Send the signal again, then unblock its delivery, so that the application's - * signal handler gets invoked. - */ - raise(demo_setjmp_signo); - sigemptyset(&new_mask); - sigaddset(&new_mask, demo_setjmp_signo); - sigprocmask(SIG_UNBLOCK, &new_mask, NULL); -/* - * Set the return status to show that a signal was caught. - */ - errno = EINTR; - status = -1; - }; -/* - * Now restore the process signal mask to how it was on entry to this - * function. - */ - sigprocmask(SIG_SETMASK, (sigset_t *) &old_mask, NULL); - return status; -} - -/*....................................................................... - * This is the main signal handler of this demonstration program. If a - * SIGINT is received by the process, it arranges that the next call - * to gl_get_line() will abort entry of the current line and start - * entering a new one. Otherwise it calls the library function which - * handles terminal resize signals and process suspension and process - * termination signals. Both of the functions called by this signal - * handler are designed to be async-signal safe, provided that the - * rules laid out in the gl_io_mode(3) man page are followed. - */ -static void demo_signal_handler(int signo) -{ - if(signo==SIGINT) - gl_abandon_line(demo_gl); - else - gl_handle_signal(signo, demo_gl, 1); -} - -/*....................................................................... - * The following signal handler is installed while select() is being - * called from within a block of code protected by sigsetjmp(). It - * simply records the signal that was caught in setjmp_signo, then - * causes the sigsetjmp() to return non-zero. - */ -static void demo_setjmp_handler(int signo) -{ - demo_setjmp_signo = signo; - siglongjmp(demo_setjmp_buffer, 1); -} - -/*....................................................................... - * This optional inactivity timeout function is used in this - * demonstration to cause gl_get_line() to wait for a small amount of - * time for I/O, before returning and allowing the event loop to - * continue. This isn't needed if you want gl_get_line() to return - * immediately, rather than blocking. - */ -static GL_TIMEOUT_FN(demo_timeout_fn) -{ - return GLTO_CONTINUE; -} - -/*....................................................................... - * Display introductory text to the user, formatted according to the - * current terminal width and enclosed in a box of asterixes. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -static void show_demo_introduction(GetLine *gl) -{ - int start; /* The column in which gl_display_text() left the cursor */ - int i; -/* - * Break the indtroductory text into an array of strings, so as to - * avoid overflowing any compiler string limits. - */ - const char *doc[] = { - "To the user this program appears to act identically to the main ", - "demo program. However whereas the code underlying the main demo ", - "program uses gl_get_line() in its default configuration, where each ", - "call blocks the caller until the user has entered a complete input ", - "line, demo3 uses gl_get_line() in its non-blocking server mode, ", - "where it must be called repeatedly from an external ", - "event loop to incrementally accept entry of the input ", - "line, as and when terminal I/O becomes possible. The well commented ", - "source code of demo3, which can be found in demo3.c, thus provides ", - "a working example of how to use gl_get_line() in a manner that ", - "doesn't block the caller. Documentation of this mode can be found ", - "in the gl_io_mode(3) man page.\n" - }; -/* - * Form the top line of the documentation box by filling the area of - * the line between a " *" prefix and a "* " suffix with asterixes. - */ - printf("\n"); - gl_display_text(gl, 0, " *", "* ", '*', 80, 0, "\n"); -/* - * Justify the documentation text within margins of asterixes. - */ - for(start=0,i=0; i<sizeof(doc)/sizeof(doc[0]) && start >= 0; i++) - start = gl_display_text(gl, 0, " * ", " * ", ' ', 80, start,doc[i]); -/* - * Draw the bottom line of the documentation box. - */ - gl_display_text(gl, 0, " *", "* ", '*', 80, 0, "\n"); - printf("\n"); -} - - -/*....................................................................... - * This is a constructor function for an object who's role is to allow - * a signal handler to be assigned to potentially all available signals, - * while preserving a copy of the original signal handlers, for later - * restration. - * - * Output: - * return SignalActions * The new object, or NULL on error. - */ -static SignalActions *new_SignalActions(void) -{ - SignalActions *si; /* The object to be returned */ -/* - * Allocate the container. - */ - si = malloc(sizeof(SignalActions)); - if(!si) { - fprintf(stderr, "new_SignalActions: 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_SignalActions(). - */ - si->nsignal = 0; - sigemptyset(&si->mask); - si->actions = NULL; -/* - * Count the number of signals that are available of the host - * platform. Note that si->mask has no members set, and that - * sigismember() is defined to return -1 if the signal number - * isn't valid. - */ - for(si->nsignal=1; sigismember(&si->mask, si->nsignal) == 0; si->nsignal++) - ; -/* - * Allocate the array of sigaction structures to use to keep a record - * of displaced signal handlers. - */ - si->actions = (struct sigaction *) malloc(sizeof(*si->actions) * si->nsignal); - if(!si->actions) { - fprintf(stderr, "Insufficient memory for %d sigaction structures.\n", - si->nsignal); - return del_SignalActions(si); - }; - return si; -} - -/*....................................................................... - * Delete a SignalActions object. - * - * Input: - * si SignalActions * The object to be deleted. - * Output: - * return SignalActions * The deleted object (always NULL). - */ -static SignalActions *del_SignalActions(SignalActions *si) -{ - if(si) { - if(si->actions) - free(si->actions); - free(si); - }; - return NULL; -} - -/*....................................................................... - * Replace the signal handlers of all of the signals in 'mask' with - * the signal handler 'handler'. - * - * Input: - * si SignalActions * The object in which to record the displaced - * signal handlers. - * mask sigset_t * The set of signals who's signal handlers - * should be displaced. - * handler void (*handler)(int) The new signal handler to assign to each - * of the signals marked in 'mask'. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int displace_signal_handlers(SignalActions *si, sigset_t *mask, - void (*handler)(int)) -{ - int signo; /* A signal number */ - struct sigaction action; /* The new signal handler */ -/* - * Mark the fact that so far we haven't displaced any signal handlers. - */ - sigemptyset(&si->mask); -/* - * Set up the description of the new signal handler. Note that - * we make sa_mask=mask. This ensures that only one instance of the - * signal handler will ever be running at one time. - */ - action.sa_handler = handler; - memcpy(&action.sa_mask, mask, sizeof(*mask)); - action.sa_flags = 0; -/* - * Check each of the available signals to see if it is specified in 'mask'. - * If so, install the new signal handler, record the displaced one in - * the corresponding element of si->actions[], and make a record in - * si->mask that this signal handler has been displaced. - */ - for(signo=1; signo < si->nsignal; signo++) { - if(sigismember(mask, signo)) { - if(sigaction(signo, &action, &si->actions[signo]) < 0) { - fprintf(stderr, "sigaction error (%s)\n", strerror(errno)); - return 1; - }; - sigaddset(&si->mask, signo); - }; - }; - return 0; -} - -/*....................................................................... - * Reinstate any signal handlers displaced by displace_signal_handlers(). - * - * Input: - * sig SignalActions * The object containing the displaced signal - * handlers. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int reinstate_signal_handlers(SignalActions *si) -{ - int signo; /* A signal number */ -/* - * Check each of the available signals to see if it is specified in - * si->mask. If so, reinstate the displaced recorded in the - * corresponding element of si->actions[], and make a record in - * si->mask that this signal handler has been reinstated. - */ - for(signo=1; signo < si->nsignal; signo++) { - if(sigismember(&si->mask, signo)) { - if(sigaction(signo, &si->actions[signo], NULL) < 0) { - fprintf(stderr, "sigaction error (%s)\n", strerror(errno)); - return 1; - }; - sigdelset(&si->mask, signo); - }; - }; - return 0; -} diff --git a/libtecla-1.6.1/direader.c b/libtecla-1.6.1/direader.c deleted file mode 100644 index 68db93f..0000000 --- a/libtecla-1.6.1/direader.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/* - * If file-system access is to be excluded, this module has no function, - * so all of its code should be excluded. - */ -#ifndef WITHOUT_FILE_SYSTEM - -/* - * 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" -#include "errmsg.h" - -/* - * Use the reentrant POSIX threads version of readdir()? - */ -#if defined(PREFER_REENTRANT) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L -#define USE_READDIR_R 1 -#endif - -/* - * Objects of the following type are used to maintain the resources - * needed to read directories. - */ -struct DirReader { - ErrMsg *err; /* The error reporting buffer */ - DIR *dir; /* The directory stream (if open, NULL otherwise) */ - struct dirent *file; /* The latest directory entry */ -#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) { - errno = ENOMEM; - 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->err = NULL; - dr->dir = NULL; - dr->file = NULL; -#ifdef USE_READDIR_R - dr->buffer = NULL; - dr->buffer_dim = 0; -#endif -/* - * Allocate a place to record error messages. - */ - dr->err = _new_ErrMsg(); - if(!dr->err) - return _del_DirReader(dr); - 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 - dr->err = _del_ErrMsg(dr->err); - 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) { - _err_record_msg(dr->err, "Can't open directory: ", path, END_ERR_MSG); - *errmsg = _err_get_msg(dr->err); - }; - return 1; - }; -/* - * Attempt to open the directory. - */ - dir = opendir(path); - if(!dir) { - if(errmsg) { - _err_record_msg(dr->err, "Can't open directory: ", path, END_ERR_MSG); - *errmsg = _err_get_msg(dr->err); - }; - 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) { - _err_record_msg(dr->err, "Unable to deduce readdir() buffer size.", - END_ERR_MSG); - *errmsg = _err_get_msg(dr->err); - }; - 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) { - _err_record_msg(dr->err, "Insufficient memory for readdir() buffer.", - END_ERR_MSG); - *errmsg = _err_get_msg(dr->err); - }; - closedir(dir); - errno = ENOMEM; - 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; - _err_clear_msg(dr->err); - }; -} - -/*....................................................................... - * 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; -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/direader.h b/libtecla-1.6.1/direader.h deleted file mode 100644 index c529231..0000000 --- a/libtecla-1.6.1/direader.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef dirreader_h -#define dirreader_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/enhance.c b/libtecla-1.6.1/enhance.c deleted file mode 100644 index bd5af1f..0000000 --- a/libtecla-1.6.1/enhance.c +++ /dev/null @@ -1,695 +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> - -#ifdef HAVE_SELECT -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif -#endif - -#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.6.1/errmsg.c b/libtecla-1.6.1/errmsg.c deleted file mode 100644 index 6abce9b..0000000 --- a/libtecla-1.6.1/errmsg.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.h> -#include <stdarg.h> - -#include "errmsg.h" - -/* - * Encapsulate the error reporting buffer in an opaque object. - */ -struct ErrMsg { - char msg[ERR_MSG_LEN+1]; /* An error message */ -}; - -/*....................................................................... - * Create a new error-message object. - * - * Output: - * return ErrMsg * The new object, or NULL on error. - */ -ErrMsg *_new_ErrMsg(void) -{ - ErrMsg *err; /* The object to be returned */ -/* - * Allocate the container. - */ - err = malloc(sizeof(ErrMsg)); - if(!err) { - errno = ENOMEM; - 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_ErrMsg(). - */ - err->msg[0] = '\0'; - return err; -} - -/*....................................................................... - * Delete an error-message object. - * - * Input: - * err ErrMsg * The object to be deleted. - * Output: - * return ErrMsg * The deleted object (always NULL). - */ -ErrMsg *_del_ErrMsg(ErrMsg *err) -{ - if(err) { - free(err); - }; - return NULL; -} - -/*....................................................................... - * Record the concatenation of a list of string arguments in an error - * message object. The last argument must be END_ERR_MSG to terminate - * the argument list. - * - * Input: - * err ErrMsg * The error-message container. - * ... const char * Zero or more strings to be concatenated in buff[]. - * ... const char * The last argument must always be END_ERR_MSG to - * terminate the argument list. - */ -void _err_record_msg(ErrMsg *err, ...) -{ - va_list ap; /* The variable argument list */ - const char *s; /* The string being printed */ - size_t msglen = 0; /* The total length of the message */ -/* - * Nowhere to record the result? - */ - if(!err) { - errno = EINVAL; - return; - }; -/* - * Concatenate the list of argument strings in err->msg[]. - */ - va_start(ap, err); - while((s = va_arg(ap, const char *)) != END_ERR_MSG) { -/* - * How much room is left in the output buffer (note that the output - * buffer has ERR_MSG_LEN+1 elements). - */ - int nleft = ERR_MSG_LEN - msglen; -/* - * How long is the next string to be appended? - */ - size_t slen = strlen(s); -/* - * If there is any room left, append as much of the string - * as will fit. - */ - if(nleft > 0) { - int nnew = slen < nleft ? slen : nleft; - strncpy(err->msg + msglen, s, nnew); - msglen += nnew; - }; - }; - va_end(ap); -/* - * Terminate the message. - */ - err->msg[msglen] = '\0'; - return; -} - -/*....................................................................... - * Return a pointer to the error message buffer. - * - * Input: - * err ErrMsg * The container of the error message buffer. - * Output: - * return char * The current error message, or NULL if err==NULL. - */ -char *_err_get_msg(ErrMsg *err) -{ - return err ? err->msg : NULL; -} - -/*....................................................................... - * Replace the current error message with an empty string. - * - * Input: - * err ErrMsg * The container of the error message buffer. - */ -void _err_clear_msg(ErrMsg *err) -{ - if(err) - err->msg[0] = '\0'; -} - diff --git a/libtecla-1.6.1/errmsg.h b/libtecla-1.6.1/errmsg.h deleted file mode 100644 index 565d7cd..0000000 --- a/libtecla-1.6.1/errmsg.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef errmsg_h -#define errmsg_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 longest expected length of an error message (excluding its - * '\0' terminator. Since any message over a nominal terminal width of - * 80 characters is going to look a mess, it makes no sense to support - * huge lengths. Note that many uses of strings declared with this - * macro assume that it will be at least 81, so don't reduce it below - * this limit. - */ -#define ERR_MSG_LEN 128 - -/* - * Provide an opaque typedef to the error-message object. - */ -typedef struct ErrMsg ErrMsg; - -/* - * The following token is used to terminate the argument lists of calls - * to _err_record_msg(). - */ -#define END_ERR_MSG ((const char *)0) - -/* - * Allocate a new error-message buffer. - */ -ErrMsg *_new_ErrMsg(void); - -/* - * Delete an error message buffer. - */ -ErrMsg *_del_ErrMsg(ErrMsg *err); - -/* - * Concatenate a list of string arguments into the specified buffer, buff[], - * which has an allocated size of buffdim characters. - * The last argument must be END_ERR_MSG to terminate the argument list. - */ -void _err_record_msg(ErrMsg *err, ...); - -/* - * Replace the current error message with an empty string. - */ -void _err_clear_msg(ErrMsg *err); - -/* - * Return a pointer to the error message buffer. This is - * a '\0' terminated character array containing ERR_MSG_LEN+1 - * elements. - */ -char *_err_get_msg(ErrMsg *err); - -#endif diff --git a/libtecla-1.6.1/expand.c b/libtecla-1.6.1/expand.c deleted file mode 100644 index b3d80e2..0000000 --- a/libtecla-1.6.1/expand.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/* - * If file-system access is to be excluded, this module has no function, - * so all of its code should be excluded. - */ -#ifndef WITHOUT_FILE_SYSTEM - -#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" -#include "ioutil.h" -#include "expand.h" -#include "errmsg.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 default number of spaces place between columns when listing - * a set of expansions. - */ -#define EF_COL_SEP 2 - -struct ExpandFile { - ErrMsg *err; /* The error reporting buffer */ - 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 */ - 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); - -/* - * Encapsulate the formatting information needed to layout a - * multi-column listing of expansions. - */ -typedef struct { - int term_width; /* The width of the terminal (characters) */ - int column_width; /* The number of characters within in each column. */ - int ncol; /* The number of columns needed */ - int nline; /* The number of lines needed */ -} EfListFormat; - -/* - * Given the current terminal width, and a list of file expansions, - * determine how to best use the terminal width to display a multi-column - * listing of expansions. - */ -static void ef_plan_listing(FileExpansion *result, int term_width, - EfListFormat *fmt); - -/* - * Display a given line of a multi-column list of file-expansions. - */ -static int ef_format_line(FileExpansion *result, EfListFormat *fmt, int lnum, - GlWriteFn *write_fn, void *data); - -/*....................................................................... - * 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) { - errno = ENOMEM; - 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->err = NULL; - 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'; -/* - * Allocate a place to record error messages. - */ - ef->err = _new_ErrMsg(); - if(!ef->err) - return del_ExpandFile(ef); -/* - * 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(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) { - errno = ENOMEM; - 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(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 error report buffer. - */ - ef->err = _del_ErrMsg(ef->err); -/* - * 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) { - _err_record_msg(ef->err, "ef_expand_file: NULL path argument", - END_ERR_MSG); - }; - errno = EINVAL; - 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)) { - _err_record_msg(ef->err, "Insufficient memory to record path", - END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "No files match", END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "Insufficient memory to record path", - END_ERR_MSG); - 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->err 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) { - _err_record_msg(ef->err, - "Insufficient memory to record all of the matching filenames", - END_ERR_MSG); - errno = ENOMEM; - 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->err. - */ -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) - _err_record_msg(ef->err, "Insufficient memory to store pathname", - END_ERR_MSG); - 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; - _err_clear_msg(ef->err); - 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->err 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) { - _err_record_msg(ef->err, "Insufficient memory to open a new directory", - END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "Insufficient memory to open a new directory", - END_ERR_MSG); - 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)) { - _err_record_msg(ef->err, errmsg, END_ERR_MSG); - 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->err. - */ -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) { - _err_record_msg(ef->err, "Insufficient memory to expand path", - END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "Environment variable name too long", - END_ERR_MSG); - return NULL; - }; -/* - * Terminate the environment variable name. - */ - ef->envnam[envlen] = '\0'; -/* - * Lookup the value of the environment variable. - */ - value = getenv(ef->envnam); - if(!value) { - _err_record_msg(ef->err, "No expansion found for: $", ef->envnam, - END_ERR_MSG); - return NULL; - }; -/* - * Copy the value of the environment variable into the output pathname. - */ - if(_pn_append_to_path(ef->path, value, -1, 0) == NULL) { - _err_record_msg(ef->err, "Insufficient memory to expand path", - END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "Insufficient memory to expand path", END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "Username too long", END_ERR_MSG); - 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) { - _err_record_msg(ef->err, _hd_last_home_dir_error(ef->home), END_ERR_MSG); - 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) { - _err_record_msg(ef->err, "Insufficient memory to expand filename", - END_ERR_MSG); - 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 ? _err_get_msg(ef->err) : "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) -{ - return _ef_output_expansions(result, _io_write_stdio, fp, term_width); -} - -/*....................................................................... - * Print out an array of matching files via a callback. - * - * Input: - * result FileExpansion * The container of the sorted array of - * expansions. - * write_fn GlWriteFn * The function to call to write the - * expansions or 0 to discard the output. - * data void * Anonymous data to pass to write_fn(). - * term_width int The width of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _ef_output_expansions(FileExpansion *result, GlWriteFn *write_fn, - void *data, int term_width) -{ - EfListFormat fmt; /* List formatting information */ - int lnum; /* The sequential number of the line to print next */ -/* - * Not enough space to list anything? - */ - if(term_width < 1) - return 0; -/* - * Do we have a callback to write via, and any expansions to be listed? - */ - if(write_fn && result && result->nfile>0) { -/* - * Work out how to arrange the listing into fixed sized columns. - */ - ef_plan_listing(result, term_width, &fmt); -/* - * Print the listing to the specified stream. - */ - for(lnum=0; lnum < fmt.nline; lnum++) { - if(ef_format_line(result, &fmt, lnum, write_fn, data)) - return 1; - }; - }; - return 0; -} - -/*....................................................................... - * Work out how to arrange a given array of completions into a listing - * of one or more fixed size columns. - * - * Input: - * result FileExpansion * The set of completions to be listed. - * term_width int The width of the terminal. A lower limit of - * zero is quietly enforced. - * Input/Output: - * fmt EfListFormat * The formatting information will be assigned - * to the members of *fmt. - */ -static void ef_plan_listing(FileExpansion *result, int term_width, - EfListFormat *fmt) -{ - int maxlen; /* The length of the longest matching string */ - int i; -/* - * Ensure that term_width >= 0. - */ - if(term_width < 0) - term_width = 0; -/* - * Start by assuming the worst case, that either nothing will fit - * on the screen, or that there are no matches to be listed. - */ - fmt->term_width = term_width; - fmt->column_width = 0; - fmt->nline = fmt->ncol = 0; -/* - * Work out the maximum length of the matching strings. - */ - 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; -/* - * Split the available terminal width into columns of - * maxlen + EF_COL_SEP characters. - */ - fmt->column_width = maxlen; - fmt->ncol = fmt->term_width / (fmt->column_width + EF_COL_SEP); -/* - * If the column width is greater than the terminal width, zero columns - * will have been selected. Set a lower limit of one column. Leave it - * up to the caller how to deal with completions who's widths exceed - * the available terminal width. - */ - if(fmt->ncol < 1) - fmt->ncol = 1; -/* - * How many lines of output will be needed? - */ - fmt->nline = (result->nfile + fmt->ncol - 1) / fmt->ncol; - return; -} - -/*....................................................................... - * Render one line of a multi-column listing of completions, using a - * callback function to pass the output to an arbitrary destination. - * - * Input: - * result FileExpansion * The container of the sorted array of - * completions. - * fmt EfListFormat * Formatting information. - * lnum int The index of the line to print, starting - * from 0, and incrementing until the return - * value indicates that there is nothing more - * to be printed. - * write_fn GlWriteFn * The function to call to write the line, or - * 0 to discard the output. - * data void * Anonymous data to pass to write_fn(). - * Output: - * return int 0 - Line printed ok. - * 1 - Nothing to print. - */ -static int ef_format_line(FileExpansion *result, EfListFormat *fmt, int lnum, - GlWriteFn *write_fn, void *data) -{ - int col; /* The index of the list column being output */ -/* - * If the line index is out of bounds, there is nothing to be written. - */ - if(lnum < 0 || lnum >= fmt->nline) - return 1; -/* - * If no output function has been provided, return as though the line - * had been printed. - */ - if(!write_fn) - return 0; -/* - * Print the matches in 'ncol' columns, sorted in line order within each - * column. - */ - for(col=0; col < fmt->ncol; col++) { - int m = col*fmt->nline + lnum; -/* - * Is there another match to be written? Note that in general - * the last line of a listing will have fewer filled columns - * than the initial lines. - */ - if(m < result->nfile) { - char *file = result->files[m]; -/* - * How long are the completion and type-suffix strings? - */ - int flen = strlen(file); -/* - * Write the completion string. - */ - if(write_fn(data, file, flen) != flen) - return 1; -/* - * If another column follows the current one, pad to its start with spaces. - */ - if(col+1 < fmt->ncol) { -/* - * The following constant string of spaces is used to pad the output. - */ - static const char spaces[] = " "; - static const int nspace = sizeof(spaces) - 1; -/* - * Pad to the next column, using as few sub-strings of the spaces[] - * array as possible. - */ - int npad = fmt->column_width + EF_COL_SEP - flen; - while(npad>0) { - int n = npad > nspace ? nspace : npad; - if(write_fn(data, spaces + nspace - n, n) != n) - return 1; - npad -= n; - }; - }; - }; - }; -/* - * Start a new line. - */ - { - char s[] = "\r\n"; - int n = strlen(s); - if(write_fn(data, s, n) != n) - return 1; - }; - return 0; -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/expand.h b/libtecla-1.6.1/expand.h deleted file mode 100644 index 8c0bad8..0000000 --- a/libtecla-1.6.1/expand.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef expand_h -#define expand_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 header is not for use by external applicatons. It contains - * internal immplementation features of the libtecla library, which - * may change incompatibly between releases. - */ - -/* - * Print a list of expansions via a callback function. - */ -int _ef_output_expansions(FileExpansion *result, GlWriteFn *write_fn, - void *data, int term_width); - - -#endif diff --git a/libtecla-1.6.1/freelist.c b/libtecla-1.6.1/freelist.c deleted file mode 100644 index 2a85ba1..0000000 --- a/libtecla-1.6.1/freelist.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 "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 */ - long ntotal; /* The total number of nodes in the free list */ - 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: - * 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(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) { - errno = ENOMEM; - 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->ntotal = 0; - fl->block = NULL; - fl->free_list = NULL; -/* - * Allocate the first block of memory. - */ - fl->block = _new_FreeListBlock(fl); - if(!fl->block) { - errno = ENOMEM; - return _del_FreeList(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: - * 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(FreeList *fl, int force) -{ - if(fl) { -/* - * Check whether any nodes are in use. - */ - if(!force && _busy_FreeListNodes(fl) != 0) { - errno = EBUSY; - 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: - * 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; -} - -/*....................................................................... - * Query the number of allocated nodes in the freelist which are - * currently unused. - * - * Input: - * fl FreeList * The list to count wrt, or NULL. - * Output: - * return long The number of unused nodes (or 0 if fl==NULL). - */ -long _idle_FreeListNodes(FreeList *fl) -{ - return fl ? (fl->ntotal - 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); -/* - * Update the record of the number of nodes in the freelist. - */ - fl->ntotal += fl->blocking_factor; - 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.6.1/freelist.h b/libtecla-1.6.1/freelist.h deleted file mode 100644 index 09d966f..0000000 --- a/libtecla-1.6.1/freelist.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef freelist_h -#define freelist_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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(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(FreeList *fl, int force); - -/* - * Determine the number of nodes that are currently in use. - */ -long _busy_FreeListNodes(FreeList *fl); - -/* - * Query the number of allocated nodes in the freelist which are - * currently unused. - */ -long _idle_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.6.1/getline.c b/libtecla-1.6.1/getline.c deleted file mode 100644 index 324aadb..0000000 --- a/libtecla-1.6.1/getline.c +++ /dev/null @@ -1,12844 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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> -#include <stdarg.h> - -/* - * UNIX headers. - */ -#include <sys/ioctl.h> -#ifdef HAVE_SELECT -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif -#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 - -/* - * 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 -typedef int TputsRetType; -typedef char TputsArgType; /* int tputs(char c, FILE *fp) */ -#define TPUTS_RETURNS_VALUE 1 -#elif defined(__APPLE__) && defined(__MACH__) -typedef void TputsRetType; -typedef int TputsArgType; /* void tputs(int c, FILE *fp) */ -#define TPUTS_RETURNS_VALUE 0 -#else -typedef int TputsRetType; -typedef int TputsArgType; /* int tputs(int c, FILE *fp) */ -#define TPUTS_RETURNS_VALUE 1 -#endif - -/* - * Use the above specifications to prototype our tputs callback function. - */ -static TputsRetType gl_tputs_putchar(TputsArgType c); - -#endif /* defined(USE_TERMINFO) || defined(USE_TERMCAP) */ - -/* - * If the library is being compiled without filesystem access facilities, - * ensure that none of the action functions that normally do access the - * filesystem are bound by default, and that it they do get bound, that - * they don't do anything. - */ -#if WITHOUT_FILE_SYSTEM -#define HIDE_FILE_SYSTEM -#endif - -/* - * POSIX headers. - */ -#include <unistd.h> -#include <fcntl.h> -#include <termios.h> - -/* - * Provide typedefs for standard POSIX structures. - */ -typedef struct sigaction SigAction; -typedef struct termios Termios; - -/* - * Which flag is used to select non-blocking I/O with fcntl()? - */ -#undef NON_BLOCKING_FLAG -#if defined(O_NONBLOCK) -#define NON_BLOCKING_FLAG (O_NONBLOCK) -#elif defined(O_NDELAY) -#define NON_BLOCKING_FLAG (O_NDELAY) -#endif - -/* - * What value should we give errno if I/O blocks when it shouldn't. - */ -#undef BLOCKED_ERRNO -#if defined(EAGAIN) -#define BLOCKED_ERRNO (EAGAIN) -#elif defined(EWOULDBLOCK) -#define BLOCKED_ERRNO (EWOULDBLOCK) -#elif defined(EIO) -#define BLOCKED_ERRNO (EIO) -#else -#define BLOCKED_ERRNO 0 -#endif - -/* - * Local headers. - */ -#ifndef WITHOUT_FILE_SYSTEM -#include "pathutil.h" -#endif -#include "libtecla.h" -#include "keytab.h" -#include "getline.h" -#include "ioutil.h" -#include "history.h" -#include "freelist.h" -#include "stringrp.h" -#include "chrqueue.h" -#include "cplmatch.h" -#ifndef WITHOUT_FILE_SYSTEM -#include "expand.h" -#endif -#include "errmsg.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; - -/* - * Set the largest key-sequence that can be handled. - */ -#define GL_KEY_MAX 64 - -/* - * 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 { - KtAction action; /* 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_terminal() */ - /* 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 - - -static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, - GlFdEvent event); - -static int gl_call_timeout_handler(GetLine *gl); - -#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 - -/* - * Completion handlers and their callback data are recorded in - * nodes of the following type. - */ -typedef struct GlCplCallback GlCplCallback; -struct GlCplCallback { - CplMatchFn *fn; /* The completion callback function */ - void *data; /* Arbitrary callback data */ -}; - -/* - * The following function is used as the default completion handler when - * the filesystem is to be hidden. It simply reports no completions. - */ -#ifdef HIDE_FILE_SYSTEM -static CPL_MATCH_FN(gl_no_completions); -#endif - -/* - * Specify how many GlCplCallback nodes are added to the GlCplCallback freelist - * whenever it becomes exhausted. - */ -#define GL_CPL_FREELIST_BLOCKING 10 - -/* - * External action functions and their callback data are recorded in - * nodes of the following type. - */ -typedef struct GlExternalAction GlExternalAction; -struct GlExternalAction { - GlActionFn *fn; /* The function which implements the action */ - void *data; /* Arbitrary callback data */ -}; - -/* - * Specify how many GlExternalAction nodes are added to the - * GlExternalAction freelist whenever it becomes exhausted. - */ -#define GL_EXT_ACT_FREELIST_BLOCKING 10 - -/* - * Define the contents of the GetLine object. - * Note that the typedef for this object can be found in libtecla.h. - */ -struct GetLine { - ErrMsg *err; /* The error-reporting buffer */ - GlHistory *glh; /* The line-history buffer */ - WordCompletion *cpl; /* String completion resource object */ - GlCplCallback cplfn; /* The completion callback */ -#ifndef WITHOUT_FILE_SYSTEM - ExpandFile *ef; /* ~user/, $envvar and wildcard expansion */ - /* resource object. */ -#endif - StringGroup *capmem; /* Memory for recording terminal capability */ - /* strings. */ - GlCharQueue *cq; /* The terminal output character queue */ - 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 */ - GlWriteFn *flush_fn; /* The function to call to write to the terminal */ - GlIOMode io_mode; /* The I/O mode established by gl_io_mode() */ - int raw_mode; /* True while the terminal is in raw mode */ - GlPendingIO pending_io; /* The type of I/O that is currently pending */ - GlReturnStatus rtn_status; /* The reason why gl_get_line() returned */ - int rtn_errno; /* THe value of errno associated with rtn_status */ - 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[] */ - 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 *cpl_mem; /* Memory for GlCplCallback objects */ - FreeList *ext_act_mem; /* Memory for GlExternalAction objects */ - FreeList *sig_mem; /* Memory for nodes of the signal list */ - GlSignalNode *sigs; /* The head of the list of signals */ - int signals_masked; /* True between calls to gl_mask_signals() and */ - /* gl_unmask_signals() */ - int signals_overriden; /* True between calls to gl_override_signals() */ - /* and gl_restore_signals() */ - sigset_t all_signal_set; /* The set of all signals that we are trapping */ - sigset_t old_signal_set; /* The set of blocked signals on entry to */ - /* gl_get_line(). */ - sigset_t use_signal_set; /* The subset of all_signal_set to unblock */ - /* while waiting for key-strokes */ - 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 term_len; /* The number of terminal characters used to */ - /* display the current input line. */ - 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[] */ - int displayed; /* True if an input line is currently displayed */ - int redisplay; /* If true, the input line will be redrawn */ - /* either after the current action function */ - /* returns, or when gl_get_input_line() */ - /* is next called. */ - int postpone; /* _gl_normal_io() sets this flag, to */ - /* postpone any redisplays until */ - /* is next called, to resume line editing. */ - char keybuf[GL_KEY_MAX+1]; /* A buffer of currently unprocessed key presses */ - int nbuf; /* The number of characters in keybuf[] */ - int nread; /* The number of characters read from keybuf[] */ - KtAction current_action; /* The action function that is being invoked */ - int current_count; /* The repeat count passed to */ - /* current_acction.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 keyseq_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. */ - int automatic_history; /* True to automatically archive entered lines */ - /* in the history list. */ - 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 */ - struct { /* Inactivity timeout related data */ - struct timeval dt; /* The inactivity timeout when timer.fn() */ - /* isn't 0 */ - GlTimeoutFn *fn; /* The application callback to call when */ - /* the inactivity timer expires, or 0 if */ - /* timeouts are not required. */ - void *data; /* Application provided data to be passed to */ - /* timer.fn(). */ - } timer; -#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 - -/* - * Enumerate the attributes needed to classify different types of - * signals. These attributes reflect the standard default - * characteristics of these signals (according to Richard Steven's - * Advanced Programming in the UNIX Environment). Note that these values - * are all powers of 2, so that they can be combined in a bitwise union. - */ -typedef enum { - GLSA_TERM=1, /* A signal that terminates processes */ - GLSA_SUSP=2, /* A signal that suspends processes */ - GLSA_CONT=4, /* A signal that is sent when suspended processes resume */ - GLSA_IGN=8, /* A signal that is ignored */ - GLSA_CORE=16, /* A signal that generates a core dump */ - GLSA_HARD=32, /* A signal generated by a hardware exception */ - GLSA_SIZE=64 /* A signal indicating terminal size changes */ -} GlSigAttr; - -/* - * 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 attr; /* The default attributes of this signal, expressed */ - /* as a bitwise union of GlSigAttr enumerators */ - int errno_value; /* What to set errno to */ -} gl_signal_list[] = { - {SIGABRT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR}, - {SIGALRM, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, - {SIGCONT, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_CONT|GLSA_IGN, 0}, -#if defined(SIGHUP) -#ifdef ENOTTY - {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, ENOTTY}, -#else - {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, -#endif -#endif - {SIGINT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, -#if defined(SIGPIPE) -#ifdef EPIPE - {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EPIPE}, -#else - {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, -#endif -#endif -#ifdef SIGPOLL - {SIGPOLL, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, -#endif -#ifdef SIGPWR - {SIGPWR, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_IGN, 0}, -#endif -#ifdef SIGQUIT - {SIGQUIT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR}, -#endif - {SIGTERM, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, -#ifdef SIGTSTP - {SIGTSTP, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, -#endif -#ifdef SIGTTIN - {SIGTTIN, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, -#endif -#ifdef SIGTTOU - {SIGTTOU, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, -#endif -#ifdef SIGUSR1 - {SIGUSR1, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, -#endif -#ifdef SIGUSR2 - {SIGUSR2, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, -#endif -#ifdef SIGVTALRM - {SIGVTALRM, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, -#endif -#ifdef SIGWINCH - {SIGWINCH, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_SIZE|GLSA_IGN, 0}, -#endif -#ifdef SIGXCPU - {SIGXCPU, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0}, -#endif -#ifdef SIGXFSZ - {SIGXFSZ, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 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); - -/* - * Respond to an externally caught process suspension or - * termination signal. - */ -static void gl_suspend_process(int signo, GetLine *gl, int ngl); - -/* Return the default attributes of a given signal */ - -static int gl_classify_signal(int signo); - -/* - * 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 GetLine *tputs_gl = NULL; - -/* - * Define a tab to be a string of 8 spaces. - */ -#define TAB_WIDTH 8 - -/* - * Lookup the current size of the terminal. - */ -static void gl_query_size(GetLine *gl, int *ncolumn, int *nline); - -/* - * 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); - -/* - * Temporarily block the delivery of all signals that gl_get_line() - * is currently configured to trap. - */ -static int gl_mask_signals(GetLine *gl, sigset_t *oldset); - -/* - * Restore the process signal mask that was overriden by a previous - * call to gl_mask_signals(). - */ -static int gl_unmask_signals(GetLine *gl, sigset_t *oldset); - -/* - * Unblock the signals that gl_get_line() has been configured to catch. - */ -static int gl_catch_signals(GetLine *gl); - -/* - * Return the set of all trappable signals. - */ -static void gl_list_trappable_signals(sigset_t *signals); - -/* - * 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); - -/* - * Switch to non-blocking I/O if possible. - */ -static int gl_nonblocking_io(GetLine *gl, int fd); - -/* - * Switch to blocking I/O if possible. - */ -static int gl_blocking_io(GetLine *gl, int fd); - -/* - * Read a line from the user in raw mode. - */ -static int gl_get_input_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); - -/* - * Query the user for a single character. - */ -static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar); - -/* - * Read input from a non-interactive input stream. - */ -static int gl_read_stream_line(GetLine *gl); - -/* - * Read a single character from a non-interactive input stream. - */ -static int gl_read_stream_char(GetLine *gl); - -/* - * Prepare to edit a new line. - */ -static int gl_present_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); - -/* - * Reset all line-editing parameters for a new input line. - */ -static void gl_reset_editor(GetLine *gl); - -/* - * 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_print_raw_string(GetLine *gl, int buffered, - const char *string, int n); - -/* - * Print an informational message, starting and finishing on new lines. - * After the list of strings to be printed, the last argument MUST be - * GL_END_INFO. - */ -static int gl_print_info(GetLine *gl, ...); -#define GL_END_INFO ((const char *)0) - -/* - * Start a newline and place the cursor at its start. - */ -static int gl_start_newline(GetLine *gl, int buffered); - -/* - * Output a terminal control sequence. - */ -static int gl_print_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_print_char(GetLine *gl, char c, char pad); -static int gl_print_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); - -/* - * Record a new character in the input-line buffer. - */ -static int gl_buffer_char(GetLine *gl, char c, int bufpos); - -/* - * Record a string in the input-line buffer. - */ -static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos); - -/* - * Make way to insert a string in the input-line buffer. - */ -static int gl_make_gap_in_buffer(GetLine *gl, int start, int n); - -/* - * Remove characters from the input-line buffer, and move any characters - * that followed them to the start of the vacated space. - */ -static void gl_remove_from_buffer(GetLine *gl, int start, int n); - -/* - * Terminate the input-line buffer after a specified number of characters. - */ -static int gl_truncate_buffer(GetLine *gl, int n); - -/* - * Delete the displayed part of the input line that follows the current - * terminal cursor position. - */ -static int gl_truncate_display(GetLine *gl); - -/* - * Accomodate changes to the contents of the input line buffer - * that weren't made by the above gl_*buffer functions. - */ -static void gl_update_buffer(GetLine *gl); - -/* - * Read a single character from the terminal. - */ -static int gl_read_terminal(GetLine *gl, int keep, char *c); - -/* - * Discard processed characters from the key-press lookahead buffer. - */ -static void gl_discard_chars(GetLine *gl, int nused); - -/* - * 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); - -/* - * How many characters are needed to write a number as an octal string? - */ -static int gl_octal_width(unsigned num); - -/* - * Return the number of spaces needed to display a tab character at - * a given location of the terminal. - */ -static int gl_displayed_tab_width(GetLine *gl, int term_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); -static int gl_report_config_error(GetLine *gl, const char *origin, int lineno, - const char *errmsg); - -/* - * 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(GetLine *gl, 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); - -/* - * The callback through which all terminal output is routed. - * This simply appends characters to a queue buffer, which is - * subsequently flushed to the output channel by gl_flush_output(). - */ -static GL_WRITE_FN(gl_write_fn); - -/* - * The callback function which the output character queue object - * calls to transfer characters to the output channel. - */ -static GL_WRITE_FN(gl_flush_terminal); - -/* - * Enumerate the possible return statuses of gl_read_input(). - */ -typedef enum { - GL_READ_OK, /* A character was read successfully */ - GL_READ_ERROR, /* A read-error occurred */ - GL_READ_BLOCKED, /* The read would have blocked the caller */ - GL_READ_EOF /* The end of the current input file was reached */ -} GlReadStatus; - -static GlReadStatus gl_read_input(GetLine *gl, char *c); -/* - * Private functions of gl_read_input(). - */ -static int gl_event_handler(GetLine *gl, int fd); -static GlReadStatus gl_read_unmasked(GetLine *gl, int fd, char *c); - - -/* - * A private function of gl_tty_signals(). - */ -static int gl_set_tty_signal(int signo, void (*handler)(int)); - -/* - * 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 to return the current input line to the caller of gl_get_line(). - */ -static int gl_line_ended(GetLine *gl, int newline_char); - -/* - * Arrange for the input line to be redisplayed when the current contents - * of the output queue have been flushed. - */ -static void gl_queue_redisplay(GetLine *gl); - -/* - * Erase the displayed representation of the input line, without - * touching the buffered copy. - */ -static int gl_erase_line(GetLine *gl); - -/* - * This function is called whenever the input line has been erased. - */ -static void gl_line_erased(GetLine *gl); - -/* - * Arrange for the current input line to be discarded. - */ -void _gl_abandon_line(GetLine *gl); - -/* - * The following are private internally callable versions of pertinent - * public functions. Unlike their public wrapper functions, they don't - * block signals while running, and assume that their arguments are valid. - * They are designed to be called from places where signals are already - * blocked, and where simple sanity checks have already been applied to - * their arguments. - */ -static char *_gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); -static int _gl_query_char(GetLine *gl, const char *prompt, char defchar); -static int _gl_read_char(GetLine *gl); -static int _gl_update_size(GetLine *gl); -/* - * Redraw the current input line to account for a change in the terminal - * size. Also install the new size in gl. - */ -static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline); - -static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, - const char *term); -static int _gl_configure_getline(GetLine *gl, const char *app_string, - const char *app_file, const char *user_file); -static int _gl_save_history(GetLine *gl, const char *filename, - const char *comment, int max_lines); -static int _gl_load_history(GetLine *gl, const char *filename, - const char *comment); -static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data); -static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline, - GlTerminalSize *size); -static void _gl_replace_prompt(GetLine *gl, const char *prompt); -static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value); -static int _gl_raw_io(GetLine *gl, int redisplay); -static int _gl_normal_io(GetLine *gl); -static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, - int list_only, const char *name, - const char *keyseq); -static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn, - const char *name, const char *keyseq); -static int _gl_io_mode(GetLine *gl, GlIOMode mode); -static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline); -static int _gl_append_history(GetLine *gl, const char *line); - -/* - * Reset the completion status and associated errno value in - * gl->rtn_status and gl->rtn_errno. - */ -static void gl_clear_status(GetLine *gl); - -/* - * Record a completion status, unless a previous abnormal completion - * status has already been recorded for the current call. - */ -static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status, - int rtn_errno); - -/* - * 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); -#ifndef HIDE_FILE_SYSTEM -static KT_KEY_FN(gl_expand_filename); -static KT_KEY_FN(gl_read_from_file); -static KT_KEY_FN(gl_read_init_files); -static KT_KEY_FN(gl_list_glob); -#endif -static KT_KEY_FN(gl_del_char_or_list_or_eof); -static KT_KEY_FN(gl_list_or_eof); -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_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_list_history); -static KT_KEY_FN(gl_list_completions); -static KT_KEY_FN(gl_run_external_action); - -/* - * 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}, -#ifndef HIDE_FILE_SYSTEM - {"expand-filename", gl_expand_filename}, - {"read-from-file", gl_read_from_file}, - {"read-init-files", gl_read_init_files}, - {"list-glob", gl_list_glob}, -#endif - {"del-char-or-list-or-eof", gl_del_char_or_list_or_eof}, - {"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}, - {"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}, - {"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"}, -#ifndef HIDE_FILE_SYSTEM - {"^X*", "expand-filename"}, - {"^X^F", "read-from-file"}, - {"^X^R", "read-init-files"}, - {"^Xg", "list-glob"}, - {"^XG", "list-glob"}, -#endif - {"^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"}, -#ifndef HIDE_FILE_SYSTEM - {"^G", "list-glob"}, -#endif - {"^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"}, -#ifndef HIDE_FILE_SYSTEM - {"^X^F", "read-from-file"}, - {"^X^R", "read-init-files"}, - {"^X*", "expand-filename"}, -#endif - {"^?", "backward-delete-char"}, - {"M- ", "cursor-right"}, - {"M-$", "end-of-line"}, -#ifndef HIDE_FILE_SYSTEM - {"M-*", "expand-filename"}, -#endif - {"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"}, -#ifndef HIDE_FILE_SYSTEM - {"M-^X^R", "read-init-files"}, -#endif - {"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) { - errno = ENOMEM; - return NULL; - }; -/* - * Allocate the container. - */ - gl = (GetLine *) malloc(sizeof(GetLine)); - if(!gl) { - errno = ENOMEM; - 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->err = NULL; - gl->glh = NULL; - gl->cpl = NULL; -#ifndef HIDE_FILE_SYSTEM - gl->cplfn.fn = cpl_file_completions; -#else - gl->cplfn.fn = gl_no_completions; -#endif - gl->cplfn.data = NULL; -#ifndef WITHOUT_FILE_SYSTEM - gl->ef = NULL; -#endif - gl->capmem = NULL; - gl->cq = NULL; - gl->input_fd = -1; - gl->output_fd = -1; - gl->input_fp = NULL; - gl->output_fp = NULL; - gl->file_fp = NULL; - gl->term = NULL; - gl->is_term = 0; - gl->flush_fn = gl_flush_terminal; - gl->io_mode = GL_NORMAL_MODE; - gl->raw_mode = 0; - gl->pending_io = GLP_WRITE; /* We will start by writing the prompt */ - gl_clear_status(gl); - gl->linelen = linelen; - gl->line = NULL; - gl->cutbuf = NULL; - gl->prompt = NULL; - gl->prompt_len = 0; - gl->prompt_changed = 0; - gl->prompt_style = GL_LITERAL_PROMPT; - gl->cpl_mem = NULL; - gl->ext_act_mem = NULL; - gl->sig_mem = NULL; - gl->sigs = NULL; - gl->signals_masked = 0; - gl->signals_overriden = 0; - sigemptyset(&gl->all_signal_set); - sigemptyset(&gl->old_signal_set); - sigemptyset(&gl->use_signal_set); - gl->bindings = NULL; - gl->ntotal = 0; - gl->buff_curpos = 0; - gl->term_curpos = 0; - gl->term_len = 0; - gl->buff_mark = 0; - gl->insert_curpos = 0; - gl->insert = 1; - gl->number = -1; - gl->endline = 1; - gl->displayed = 0; - gl->redisplay = 0; - gl->postpone = 0; - gl->keybuf[0]='\0'; - gl->nbuf = 0; - gl->nread = 0; - gl->current_action.fn = 0; - gl->current_action.data = NULL; - 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->automatic_history = 1; - gl->vi.undo.line = NULL; - gl->vi.undo.buff_curpos = 0; - gl->vi.undo.ntotal = 0; - gl->vi.undo.saved = 0; - gl->vi.repeat.action.fn = 0; - gl->vi.repeat.action.data = 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->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; - gl->timer.dt.tv_sec = 0; - gl->timer.dt.tv_usec = 0; - gl->timer.fn = 0; - gl->timer.data = NULL; -#endif -/* - * Allocate an error reporting buffer. - */ - gl->err = _new_ErrMsg(); - if(!gl->err) - return del_GetLine(gl); -/* - * 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. - */ -#ifndef WITHOUT_FILE_SYSTEM - gl->ef = new_ExpandFile(); - if(!gl->ef) - return del_GetLine(gl); -#endif -/* - * 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 the character queue that is used to buffer terminal output. - */ - gl->cq = _new_GlCharQueue(); - if(!gl->cq) - 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) { - errno = ENOMEM; - return del_GetLine(gl); - }; -/* - * Start with an empty input line. - */ - gl_truncate_buffer(gl, 0); -/* - * Allocate a cut buffer. - */ - gl->cutbuf = (char *) malloc(linelen + 2); - if(!gl->cutbuf) { - errno = ENOMEM; - return del_GetLine(gl); - }; - gl->cutbuf[0] = '\0'; -/* - * Allocate an initial empty prompt. - */ - _gl_replace_prompt(gl, NULL); - if(!gl->prompt) { - errno = ENOMEM; - return del_GetLine(gl); - }; -/* - * Allocate a vi undo buffer. - */ - gl->vi.undo.line = (char *) malloc(linelen + 2); - if(!gl->vi.undo.line) { - errno = ENOMEM; - return del_GetLine(gl); - }; - gl->vi.undo.line[0] = '\0'; -/* - * Allocate a freelist from which to allocate nodes for the list - * of completion functions. - */ - gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING); - if(!gl->cpl_mem) - return del_GetLine(gl); -/* - * Allocate a freelist from which to allocate nodes for the list - * of external action functions. - */ - gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction), - GL_EXT_ACT_FREELIST_BLOCKING); - if(!gl->ext_act_mem) - return del_GetLine(gl); -/* - * Allocate a freelist from which to allocate nodes for the list - * of signals. - */ - gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING); - if(!gl->sig_mem) - return del_GetLine(gl); -/* - * Install initial 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, NULL)) - 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) { - errno = ENOMEM; - 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(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) { -/* - * If the terminal is in raw server mode, reset it. - */ - _gl_normal_io(gl); -/* - * Deallocate all objects contained by gl. - */ - gl->err = _del_ErrMsg(gl->err); - gl->glh = _del_GlHistory(gl->glh); - gl->cpl = del_WordCompletion(gl->cpl); -#ifndef WITHOUT_FILE_SYSTEM - gl->ef = del_ExpandFile(gl->ef); -#endif - gl->capmem = _del_StringGroup(gl->capmem); - gl->cq = _del_GlCharQueue(gl->cq); - if(gl->file_fp) - fclose(gl->file_fp); - if(gl->term) - free(gl->term); - if(gl->line) - free(gl->line); - if(gl->cutbuf) - free(gl->cutbuf); - if(gl->prompt) - free(gl->prompt); - gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1); - gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1); - gl->sig_mem = _del_FreeList(gl->sig_mem, 1); - gl->sigs = NULL; /* Already freed by freeing sig_mem */ - gl->bindings = _del_KeyTab(gl->bindings); - if(gl->vi.undo.line) - free(gl->vi.undo.line); -#ifdef USE_TERMCAP - if(gl->tgetent_buf) - free(gl->tgetent_buf); - if(gl->tgetstr_buf) - free(gl->tgetstr_buf); -#endif - if(gl->app_file) - free(gl->app_file); - if(gl->user_file) - free(gl->user_file); -#ifdef HAVE_SELECT - gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1); - gl->fd_nodes = NULL; /* Already freed by freeing gl->fd_node_mem */ -#endif -/* - * Delete the now empty container. - */ - 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. - */ - if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - return 1; - }; - return 0; -} - -/*....................................................................... - * 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) -{ - char *retval; /* The return value of _gl_get_line() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return NULL; - }; -/* - * Temporarily block all of the signals that we have been asked to trap. - */ - if(gl_mask_signals(gl, &gl->old_signal_set)) - return NULL; -/* - * Perform the command-line editing task. - */ - retval = _gl_get_line(gl, prompt, start_line, start_pos); -/* - * Restore the process signal mask to how it was when this function was - * first called. - */ - gl_unmask_signals(gl, &gl->old_signal_set); - return retval; -} - - -/*....................................................................... - * This is the main body of the public function gl_get_line(). - */ -static char *_gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos) -{ - int waserr = 0; /* True if an error occurs */ -/* - * Assume that this call will successfully complete the input - * line until proven otherwise. - */ - gl_clear_status(gl); -/* - * 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; - }; -/* - * 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_io(gl, 1); -/* - * Attempt to read the line. This will require more than one attempt if - * either a current temporary input file is opened by gl_get_input_line() - * or the end of a temporary input file is reached by gl_read_stream_line(). - */ - while(!waserr) { -/* - * Read a line from a non-interactive stream? - */ - if(gl->file_fp || !gl->is_term) { - if(gl_read_stream_line(gl)==0) { - break; - } else if(gl->file_fp) { - gl_revert_input(gl); - gl_record_status(gl, GLR_NEWLINE, 0); - } else { - waserr = 1; - break; - }; - }; -/* - * Read from the terminal? Note that the above if() block may have - * changed gl->file_fp, so it is necessary to retest it here, rather - * than using an else statement. - */ - if(!gl->file_fp && gl->is_term) { - if(gl_get_input_line(gl, prompt, start_line, start_pos)) - waserr = 1; - else - break; - }; - }; -/* - * If an error occurred, but gl->rtn_status is still set to - * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise - * leave it at whatever specific value was assigned by the function - * that aborted input. This means that only functions that trap - * non-generic errors have to remember to update gl->rtn_status - * themselves. - */ - if(waserr && gl->rtn_status == GLR_NEWLINE) - gl_record_status(gl, GLR_ERROR, errno); -/* - * Restore terminal settings. - */ - if(gl->io_mode != GL_SERVER_MODE) - _gl_normal_io(gl); -/* - * Restore the signal handlers. - */ - gl_restore_signal_handlers(gl); -/* - * If gl_get_line() gets aborted early, the errno value associated - * with the event that caused this to happen is recorded in - * gl->rtn_errno. Since errno may have been overwritten by cleanup - * functions after this, restore its value to the value that it had - * when the error condition occured, so that the caller can examine it - * to find out what happened. - */ - errno = gl->rtn_errno; -/* - * Check the completion status to see how to return. - */ - switch(gl->rtn_status) { - case GLR_NEWLINE: /* Success */ - return gl->line; - case GLR_BLOCKED: /* These events abort the current input line, */ - case GLR_SIGNAL: /* when in normal blocking I/O mode, but only */ - case GLR_TIMEOUT: /* temporarily pause line editing when in */ - case GLR_FDABORT: /* non-blocking server I/O mode. */ - if(gl->io_mode != GL_SERVER_MODE) - _gl_abandon_line(gl); - return NULL; - case GLR_ERROR: /* Unrecoverable errors abort the input line, */ - case GLR_EOF: /* regardless of the I/O mode. */ - default: - _gl_abandon_line(gl); - return NULL; - }; -} - -/*....................................................................... - * Read a single character from the user. - * - * Input: - * gl GetLine * A resource object returned by new_GetLine(). - * prompt char * The prompt to prefix the line with, or NULL if - * no prompt is required. - * defchar char The character to substitute if the - * user simply hits return, or '\n' if you don't - * need to substitute anything. - * Output: - * return int The character that was read, or EOF if the read - * had to be aborted (in which case you can call - * gl_return_status() to find out why). - */ -int gl_query_char(GetLine *gl, const char *prompt, char defchar) -{ - int retval; /* The return value of _gl_query_char() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return EOF; - }; -/* - * Temporarily block all of the signals that we have been asked to trap. - */ - if(gl_mask_signals(gl, &gl->old_signal_set)) - return EOF; -/* - * Perform the character reading task. - */ - retval = _gl_query_char(gl, prompt, defchar); -/* - * Restore the process signal mask to how it was when this function was - * first called. - */ - gl_unmask_signals(gl, &gl->old_signal_set); - return retval; -} - -/*....................................................................... - * This is the main body of the public function gl_query_char(). - */ -static int _gl_query_char(GetLine *gl, const char *prompt, char defchar) -{ - int c = EOF; /* The character to be returned */ - int waserr = 0; /* True if an error occurs */ -/* - * Assume that this call will successfully complete the input operation - * until proven otherwise. - */ - gl_clear_status(gl); -/* - * If this is the first call to this function or gl_get_line(), - * since new_GetLine(), complete any postponed configuration. - */ - if(!gl->configured) { - (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); - gl->configured = 1; - }; -/* - * 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 without redisplaying any partially entered - * input line. - */ - waserr = waserr || _gl_raw_io(gl, 0); -/* - * Attempt to read the line. This will require more than one attempt if - * either a current temporary input file is opened by gl_get_input_line() - * or the end of a temporary input file is reached by gl_read_stream_line(). - */ - while(!waserr) { -/* - * Read a line from a non-interactive stream? - */ - if(gl->file_fp || !gl->is_term) { - c = gl_read_stream_char(gl); - if(c != EOF) { /* Success? */ - if(c=='\n') c = defchar; - break; - } else if(gl->file_fp) { /* End of temporary input file? */ - gl_revert_input(gl); - gl_record_status(gl, GLR_NEWLINE, 0); - } else { /* An error? */ - waserr = 1; - break; - }; - }; -/* - * Read from the terminal? Note that the above if() block may have - * changed gl->file_fp, so it is necessary to retest it here, rather - * than using an else statement. - */ - if(!gl->file_fp && gl->is_term) { - c = gl_get_query_char(gl, prompt, defchar); - if(c==EOF) - waserr = 1; - else - break; - }; - }; -/* - * If an error occurred, but gl->rtn_status is still set to - * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise - * leave it at whatever specific value was assigned by the function - * that aborted input. This means that only functions that trap - * non-generic errors have to remember to update gl->rtn_status - * themselves. - */ - if(waserr && gl->rtn_status == GLR_NEWLINE) - gl_record_status(gl, GLR_ERROR, errno); -/* - * Restore terminal settings. - */ - if(gl->io_mode != GL_SERVER_MODE) - _gl_normal_io(gl); -/* - * Restore the signal handlers. - */ - gl_restore_signal_handlers(gl); -/* - * If this function gets aborted early, the errno value associated - * with the event that caused this to happen is recorded in - * gl->rtn_errno. Since errno may have been overwritten by cleanup - * functions after this, restore its value to the value that it had - * when the error condition occured, so that the caller can examine it - * to find out what happened. - */ - errno = gl->rtn_errno; -/* - * Error conditions are signalled to the caller, by setting the returned - * character to EOF. - */ - if(gl->rtn_status != GLR_NEWLINE) - c = EOF; -/* - * In this mode, every character that is read is a completed - * transaction, just like reading a completed input line, so prepare - * for the next input line or character. - */ - _gl_abandon_line(gl); -/* - * Return the acquired character. - */ - return c; -} - -/*....................................................................... - * 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; - memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t)); - act.sa_flags = 0; -/* - * Get the subset of the signals that we are supposed to trap that - * should actually be trapped. - */ - sigemptyset(&gl->use_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->use_signal_set, sig->signo) == -1) { - _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG); - return 1; - }; - }; - }; -/* - * Override the actions of the signals that we are trapping. - */ - for(sig=gl->sigs; sig; sig=sig->next) { - if(sigismember(&gl->use_signal_set, sig->signo)) { - sigdelset(&act.sa_mask, sig->signo); - if(sigaction(sig->signo, &act, &sig->original)) { - _err_record_msg(gl->err, "sigaction error", END_ERR_MSG); - return 1; - }; - sigaddset(&act.sa_mask, sig->signo); - }; - }; -/* - * Record the fact that the application's signal handlers have now - * been overriden. - */ - gl->signals_overriden = 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. - */ - if(_gl_update_size(gl)) - return 1; - 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->use_signal_set, sig->signo) && - sigaction(sig->signo, &sig->original, NULL)) { - _err_record_msg(gl->err, "sigaction error", END_ERR_MSG); - return 1; - }; - }; -/* - * Record the fact that the application's signal handlers have now - * been restored. - */ - gl->signals_overriden = 0; - 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 */ -/* - * If the terminal is already in raw mode, do nothing. - */ - if(gl->raw_mode) - return 0; -/* - * Record the current terminal attributes. - */ - if(tcgetattr(gl->input_fd, &gl->oldattr)) { - _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); - 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] = gl->io_mode==GL_SERVER_MODE ? 0:1; - newattr.c_cc[VTIME] = 0; -/* - * Install the new terminal modes. - */ - while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) { - if(errno != EINTR) { - _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); - return 1; - }; - }; -/* - * Record the new terminal mode. - */ - gl->raw_mode = 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; -/* - * If not in raw mode, do nothing. - */ - if(!gl->raw_mode) - return 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) { - _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); - waserr = 1; - break; - }; - }; -/* - * Record the new terminal mode. - */ - gl->raw_mode = 0; - return waserr; -} - -/*....................................................................... - * Switch the terminal file descriptor to use non-blocking I/O. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * fd int The file descriptor to make non-blocking. - */ -static int gl_nonblocking_io(GetLine *gl, int fd) -{ - int fcntl_flags; /* The new file-descriptor control flags */ -/* - * Is non-blocking I/O supported on this system? Note that even - * without non-blocking I/O, the terminal will probably still act as - * though it was non-blocking, because we also set the terminal - * attributes to return immediately if no input is available and we - * use select() to wait to be able to write. If select() also isn't - * available, then input will probably remain fine, but output could - * block, depending on the behaviour of the terminal driver. - */ -#if defined(NON_BLOCKING_FLAG) -/* - * Query the current file-control flags, and add the - * non-blocking I/O flag. - */ - fcntl_flags = fcntl(fd, F_GETFL) | NON_BLOCKING_FLAG; -/* - * Install the new control flags. - */ - if(fcntl(fd, F_SETFL, fcntl_flags) == -1) { - _err_record_msg(gl->err, "fcntl error", END_ERR_MSG); - return 1; - }; -#endif - return 0; -} - -/*....................................................................... - * Switch to blocking terminal I/O. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * fd int The file descriptor to make blocking. - */ -static int gl_blocking_io(GetLine *gl, int fd) -{ - int fcntl_flags; /* The new file-descriptor control flags */ -/* - * Is non-blocking I/O implemented on this system? - */ -#if defined(NON_BLOCKING_FLAG) -/* - * Query the current file control flags and remove the non-blocking - * I/O flag. - */ - fcntl_flags = fcntl(fd, F_GETFL) & ~NON_BLOCKING_FLAG; -/* - * Install the modified control flags. - */ - if(fcntl(fd, F_SETFL, fcntl_flags) == -1) { - _err_record_msg(gl->err, "fcntl error", END_ERR_MSG); - return 1; - }; -#endif - return 0; -} - -/*....................................................................... - * Read a new input line from the user. - * - * Input: - * gl GetLine * The resource object of this library. - * prompt char * The prompt to prefix the line with, or NULL to - * use the same prompt that was used by the previous - * line. - * 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 *prompt, - const char *start_line, int start_pos) -{ - char c; /* The character being read */ -/* - * Flush any pending output to the terminal. - */ - if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) - return 1; -/* - * Are we starting a new line? - */ - if(gl->endline) { -/* - * Delete any incompletely enterred line. - */ - if(gl_erase_line(gl)) - return 1; -/* - * Display the new line to be edited. - */ - if(gl_present_line(gl, prompt, start_line, start_pos)) - return 1; - }; -/* - * Read one character at a time. - */ - while(gl_read_terminal(gl, 1, &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, c); - }; -/* - * To get here, gl_read_terminal() must have returned non-zero. See - * whether a signal was caught that requested that the current line - * be returned. - */ - if(gl->endline) - return gl_line_ended(gl, '\n'); -/* - * If I/O blocked while attempting to get the latest character - * of the key sequence, rewind the key buffer to allow interpretation of - * the current key sequence to be restarted on the next call to this - * function. - */ - if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ) - gl->nread = 0; - return 1; -} - -/*....................................................................... - * This is the private function of gl_query_char() that handles - * prompting the user, reading a character from the terminal, and - * displaying what the user entered. - * - * Input: - * gl GetLine * The resource object of this library. - * prompt char * The prompt to prefix the line with. - * defchar char The character to substitute if the - * user simply hits return, or '\n' if you don't - * need to substitute anything. - * Output: - * return int The character that was read, or EOF if something - * prevented a character from being read. - */ -static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar) -{ - char c; /* The character being read */ - int retval; /* The return value of this function */ -/* - * Flush any pending output to the terminal. - */ - if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) - return EOF; -/* - * Delete any incompletely entered line. - */ - if(gl_erase_line(gl)) - return EOF; -/* - * Reset the line input parameters and display the prompt, if any. - */ - if(gl_present_line(gl, prompt, NULL, 0)) - return EOF; -/* - * Read one character. - */ - if(gl_read_terminal(gl, 1, &c) == 0) { -/* - * In this mode, count each character as being a new key-sequence. - */ - gl->keyseq_count++; -/* - * Delete the character that was read, from the key-press buffer. - */ - gl_discard_chars(gl, gl->nread); -/* - * Convert carriage returns to newlines. - */ - if(c == '\r') - c = '\n'; -/* - * If the user just hit return, subsitute the default character. - */ - if(c == '\n') - c = defchar; -/* - * Display the entered character to the right of the prompt. - */ - if(c!='\n') { - if(gl_end_of_line(gl, 1, NULL)==0) - gl_print_char(gl, c, ' '); - }; -/* - * Record the return character, and mark the call as successful. - */ - retval = c; - gl_record_status(gl, GLR_NEWLINE, 0); -/* - * Was a signal caught whose disposition is to cause the current input - * line to be returned? If so return a newline character. - */ - } else if(gl->endline) { - retval = '\n'; - gl_record_status(gl, GLR_NEWLINE, 0); - } else { - retval = EOF; - }; -/* - * Start a new line. - */ - if(gl_start_newline(gl, 1)) - return EOF; -/* - * Attempt to flush any pending output. - */ - (void) gl_flush_output(gl); -/* - * Return either the character that was read, or EOF if an error occurred. - */ - return retval; -} - -/*....................................................................... - * 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) - gl_make_gap_in_buffer(gl, buff_curpos, 1); -/* - * Copy the character into the buffer. - */ - gl_buffer_char(gl, c, buff_curpos); - gl->buff_curpos++; -/* - * 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_print_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 width of the character being overwritten. - */ - int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos], - term_curpos); -/* - * Overwrite the character in the buffer. - */ - gl_buffer_char(gl, c, buff_curpos); -/* - * 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_print_string(gl, gl->line + buff_curpos, '\0')) - return 1; -/* - * Clear to the end of the terminal. - */ - if(gl_truncate_display(gl)) - 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_print_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_buffer_char(gl, c, buff_curpos); - gl->buff_curpos++; -/* - * Overwrite the original character. - */ - if(gl_print_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) - gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen); -/* - * Copy the string into the buffer. - */ - gl_buffer_string(gl, s, buff_slen, gl->buff_curpos); - gl->buff_curpos += buff_slen; -/* - * 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_print_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. - * keep int If true, the returned character will be kept in - * the input buffer, for potential replays. It should - * subsequently be removed from the buffer when the - * key sequence that it belongs to has been fully - * processed, by calling gl_discard_chars(). - * Input/Output: - * c char * The character that is read, is assigned to *c. - * 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_terminal(GetLine *gl, int keep, char *c) -{ -/* - * Before waiting for a new character to be input, flush unwritten - * characters to the terminal. - */ - if(gl_flush_output(gl)) - return 1; -/* - * Record the fact that we are about to read from the terminal. - */ - gl->pending_io = GLP_READ; -/* - * If there is already an unread character in the buffer, - * return it. - */ - if(gl->nread < gl->nbuf) { - *c = gl->keybuf[gl->nread]; -/* - * Retain the character in the key buffer, but mark it as having been read? - */ - if(keep) { - gl->nread++; -/* - * Completely remove the character from the key buffer? - */ - } else { - memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1, - gl->nbuf - gl->nread - 1); - }; - return 0; - }; -/* - * Make sure that there is space in the key buffer for one more character. - * This should always be true if gl_interpret_char() is called for each - * new character added, since it will clear the buffer once it has recognized - * or rejected a key sequence. - */ - if(gl->nbuf + 1 > GL_KEY_MAX) { - gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.", - GL_END_INFO); - errno = EIO; - return 1; - }; -/* - * Read one character from the terminal. - */ - switch(gl_read_input(gl, c)) { - case GL_READ_OK: - break; - case GL_READ_BLOCKED: - gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); - return 1; - break; - default: - return 1; - break; - }; -/* - * Append the character to the key buffer? - */ - if(keep) { - gl->keybuf[gl->nbuf] = *c; - gl->nread = ++gl->nbuf; - }; - return 0; -} - -/*....................................................................... - * Read one or more keypresses from the terminal of an input stream. - * - * Input: - * gl GetLine * The resource object of this module. - * c char * The character that was read is assigned to *c. - * Output: - * return GlReadStatus The completion status of the read operation. - */ -static GlReadStatus gl_read_input(GetLine *gl, char *c) -{ -/* - * We may have to repeat the read if window change signals are received. - */ - for(;;) { -/* - * Which file descriptor should we read from? Mark this volatile, so - * that siglongjmp() can't clobber it. - */ - volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd; -/* - * If the endline flag becomes set, don't wait for another character. - */ - if(gl->endline) - return GL_READ_ERROR; -/* - * Since the code in this function can block, trap signals. - */ - if(sigsetjmp(gl_setjmp_buffer, 1)==0) { -/* - * Handle the different I/O modes. - */ - switch(gl->io_mode) { -/* - * In normal I/O mode, we call the event handler before attempting - * to read, since read() blocks. - */ - case GL_NORMAL_MODE: - if(gl_event_handler(gl, fd)) - return GL_READ_ERROR; - return gl_read_unmasked(gl, fd, c); /* Read one character */ - break; -/* - * In non-blocking server I/O mode, we attempt to read a character, - * and only if this fails, call the event handler to wait for a any - * user-configured timeout and any other user-configured events. In - * addition, we turn off the fcntl() non-blocking flag when reading - * from the terminal, to work around a bug in Solaris. We can do this - * without causing the read() to block, because when in non-blocking - * server-I/O mode, gl_raw_io() sets the VMIN terminal attribute to 0, - * which tells the terminal driver to return immediately if no - * characters are available to be read. - */ - case GL_SERVER_MODE: - { - GlReadStatus status; /* The return status */ - if(isatty(fd)) /* If we reading from a terminal, */ - gl_blocking_io(gl, fd); /* switch to blocking I/O */ - status = gl_read_unmasked(gl, fd, c); /* Try reading */ - if(status == GL_READ_BLOCKED) { /* Nothing readable yet */ - if(gl_event_handler(gl, fd)) /* Wait for input */ - status = GL_READ_ERROR; - else - status = gl_read_unmasked(gl, fd, c); /* Try reading again */ - }; - gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */ - return status; - }; - break; - }; - }; -/* - * 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. - * - * First, if non-blocking I/O was temporarily disabled, reinstate it. - */ - if(gl->io_mode == GL_SERVER_MODE) - gl_nonblocking_io(gl, fd); -/* - * Now respond to the signal that was caught. - */ - if(gl_check_caught_signal(gl)) - return GL_READ_ERROR; - }; -} - -/*....................................................................... - * This is a private function of gl_read_input(), which unblocks signals - * temporarily while it reads a single character from the specified file - * descriptor. - * - * Input: - * gl GetLine * The resource object of this module. - * fd int The file descriptor to read from. - * c char * The character that was read is assigned to *c. - * Output: - * return GlReadStatus The completion status of the read. - */ -static GlReadStatus gl_read_unmasked(GetLine *gl, int fd, char *c) -{ - int nread; /* The return value of read() */ -/* - * Unblock the signals that we are trapping, while waiting for I/O. - */ - gl_catch_signals(gl); -/* - * Attempt to read one character from the terminal, restarting the read - * if any signals that we aren't trapping, are received. - */ - do { - errno = 0; - nread = read(fd, c, 1); - } while(nread < 0 && errno==EINTR); -/* - * Block all of the signals that we are trapping. - */ - gl_mask_signals(gl, NULL); -/* - * Check the completion status of the read. - */ - switch(nread) { - case 1: - return GL_READ_OK; - case 0: - return (isatty(fd) || errno != 0) ? GL_READ_BLOCKED : GL_READ_EOF; - default: - return GL_READ_ERROR; - }; -} - -/*....................................................................... - * Remove a specified number of characters from the start of the - * key-press lookahead buffer, gl->keybuf[], and arrange for the next - * read to start from the character at the start of the shifted buffer. - * - * Input: - * gl GetLine * The resource object of this module. - * nused int The number of characters to discard from the start - * of the buffer. - */ -static void gl_discard_chars(GetLine *gl, int nused) -{ - int nkeep = gl->nbuf - nused; - if(nkeep > 0) { - memmove(gl->keybuf, gl->keybuf + nused, nkeep); - gl->nbuf = nkeep; - gl->nread = 0; - } else { - gl->nbuf = gl->nread = 0; - }; -} - -/*....................................................................... - * 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 */ - unsigned flags; /* The signal processing flags to use */ - int signo; /* The signal to be handled */ -/* - * Was no signal caught? - */ - if(gl_pending_signal == -1) - return 0; -/* - * Get the signal to be handled. - */ - signo = gl_pending_signal; -/* - * Mark the signal as handled. Note that at this point, all of - * the signals that we are trapping are blocked from delivery. - */ - gl_pending_signal = -1; -/* - * Record the signal that was caught, so that the user can query it later. - */ - gl->last_signal = signo; -/* - * In non-blocking server mode, the application is responsible for - * responding to terminal signals, and we don't want gl_get_line()s - * normal signal handling to clash with this, so whenever a signal - * is caught, we arrange for gl_get_line() to abort and requeue the - * signal while signals are still blocked. If the application - * had the signal unblocked when gl_get_line() was called, the signal - * will be delivered again as soon as gl_get_line() restores the - * process signal mask, just before returning to the application. - * Note that the caller of this function should set gl->pending_io - * to the appropriate choice of GLP_READ and GLP_WRITE, before returning. - */ - if(gl->io_mode==GL_SERVER_MODE) { - gl_record_status(gl, GLR_SIGNAL, EINTR); - raise(signo); - return 1; - }; -/* - * Lookup the requested disposition of this signal. - */ - for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next) - ; - if(!sig) - return 0; -/* - * Get the signal response flags for this signal. - */ - flags = sig->flags; -/* - * Only perform terminal-specific actions if the session is interactive. - */ - if(gl->is_term) { -/* - * Did we receive a terminal size signal? - */ -#ifdef SIGWINCH - if(signo == SIGWINCH && _gl_update_size(gl)) - return 1; -#endif -/* - * Start a fresh line? - */ - if(flags & GLS_RESTORE_LINE) { - if(gl_start_newline(gl, 0)) - return 1; - }; -/* - * Restore terminal settings to how they were before gl_get_line() was - * called? - */ - if(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(flags & GLS_RESTORE_SIG) { - gl_restore_signal_handlers(gl); - gl_unmask_signals(gl, &gl->old_signal_set); - } 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(!(flags & GLS_DONT_FORWARD)) - raise(signo); -/* - * Reinstate our signal handlers. - */ - if(flags & GLS_RESTORE_SIG) { - gl_mask_signals(gl, NULL); - gl_override_signal_handlers(gl); - } else { - (void) sigaction(sig->signo, &keep_action, NULL); - (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL); - }; -/* - * Prepare the terminal for continued editing, if this is an interactive - * session. - */ - if(gl->is_term) { -/* - * Do we need to reinstate our terminal settings? - */ - if(flags & GLS_RESTORE_TTY) - gl_raw_terminal_mode(gl); -/* - * Redraw the line? - */ - if(flags & GLS_REDRAW_LINE) - gl_queue_redisplay(gl); - }; -/* - * What next? - */ - switch(sig->after) { - case GLS_RETURN: - gl_newline(gl, 1, NULL); - return gl->is_term && gl_flush_output(gl); - break; - case GLS_ABORT: - gl_record_status(gl, GLR_SIGNAL, sig->errno_value); - return 1; - break; - case GLS_CONTINUE: - return gl->is_term && gl_flush_output(gl); - 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 - { - int errret; - if(!term || setupterm((char *)term, gl->input_fd, &errret) == 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) { - gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)", - "\". Will assume vt100.", GL_END_INFO); - }; -/* - * 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, NULL); - 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_terminal(gl, 1, &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 width of a tab character at a given position when - * displayed at a given position on the terminal. This is needed - * because the width of tab characters depends on where they are, - * relative to the preceding tab stops. - * - * Input: - * gl GetLine * The resource object of this library. - * term_curpos int The destination terminal location of the character. - * Output: - * return int The number of terminal charaters needed. - */ -static int gl_displayed_tab_width(GetLine *gl, int term_curpos) -{ - return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH); -} - -/*....................................................................... - * 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 gl_displayed_tab_width(gl, term_curpos); - if(IS_CTRL_CHAR(c)) - return 2; - if(!isprint((int)(unsigned char) c)) - return gl_octal_width((int)(unsigned char)c) + 1; - 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 verbatim to the current terminal or output stream. - * - * Note that when async-signal safety is required, the 'buffered' - * argument must be 0, and n must not be -1. - * - * Input: - * gl GetLine * The resource object of the gl_get_line(). - * buffered int If true, used buffered I/O when writing to - * the terminal. Otherwise use async-signal-safe - * unbuffered I/O. - * string const char * The string to be written (this need not be - * '\0' terminated unless n<0). - * n int The number of characters to write from the - * prefix of string[], or -1 to request that - * gl_print_raw_string() use strlen() to figure - * out the length. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_print_raw_string(GetLine *gl, int buffered, - const char *string, int n) -{ - GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn; -/* - * Only display output when echoing is turned on. - */ - if(gl->echo) { - int ndone = 0; /* The number of characters written so far */ -/* - * When using un-buffered I/O, flush pending output first. - */ - if(!buffered) { - if(gl_flush_output(gl)) - return 1; - }; -/* - * If no length has been provided, measure the length of the string. - */ - if(n < 0) - n = strlen(string); -/* - * Write the string. - */ - if(write_fn(gl, string + ndone, n-ndone) != n) - 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_print_control_sequence(GetLine *gl, int nline, const char *string) -{ - int waserr = 0; /* True if an error occurs */ -/* - * Only write characters to the terminal when echoing is enabled. - */ - if(gl->echo) { -#if defined(USE_TERMINFO) || defined(USE_TERMCAP) - tputs_gl = gl; - errno = 0; - tputs((char *)string, nline, gl_tputs_putchar); - waserr = errno != 0; -#else - waserr = gl_print_raw_string(gl, 1, string, -1); -#endif - }; - return waserr; -} - -#if defined(USE_TERMINFO) || defined(USE_TERMCAP) -/*....................................................................... - * The following callback function is called by tputs() to output a raw - * control character to the terminal. - */ -static TputsRetType gl_tputs_putchar(TputsArgType c) -{ - char ch = c; -#if TPUTS_RETURNS_VALUE - return gl_print_raw_string(tputs_gl, 1, &ch, 1); -#else - (void) gl_print_raw_string(tputs_gl, 1, &ch, 1); -#endif -} -#endif - -/*....................................................................... - * 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. */ -/* - * Do nothing if the input line isn't currently displayed. In this - * case, the cursor will be moved to the right place when the line - * is next redisplayed. - */ - if(!gl->displayed) - return 0; -/* - * 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_print_control_sequence(gl, 1, gl->down)) - return 1; - }; -/* - * Move up to the previous line. - */ - for(; cur_row > new_row; cur_row--) { - if(gl_print_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_print_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_print_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_print_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_print_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_print_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_tab_width(gl, 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_print_raw_string(gl, 1, string, -1)) - 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; -/* - * Keep a record of the number of characters in the terminal version - * of the input line. - */ - if(gl->term_curpos > gl->term_len) - gl->term_len = gl->term_curpos; -/* - * 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_print_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_print_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_print_char(gl, *cptr, nextc ? nextc : pad)) - return 1; - }; - return 0; -} - -/*....................................................................... - * 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_truncate_buffer(gl, 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_truncate_display(gl)) - 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_truncate_buffer(gl, gl->buff_curpos); -/* - * Clear the part of the line that follows the cursor. - */ - if(gl_truncate_display(gl)) - 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) { - gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore, - gl->buff_curpos); - }; -/* - * 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_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ? - gl->vi.undo.ntotal : gl->buff_curpos); - }; - } else { -/* - * Copy the remaining part of the line back over the deleted characters. - */ - gl_remove_from_buffer(gl, gl->buff_curpos, nc); - }; -/* - * Redraw the remaining characters following the cursor. - */ - if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0')) - return 1; -/* - * Clear to the end of the terminal. - */ - if(gl_truncate_display(gl)) - 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, NULL) || - 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, NULL); - else - return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL); -} - -/*....................................................................... - * 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, NULL); - else - return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL); - }; - 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, NULL)) - 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, NULL)) - 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)) - gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos); - gl->buff_curpos++; -/* - * 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_print_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)) - gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos); - gl->buff_curpos++; -/* - * 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_print_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)) - gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line); - } else { - if(isupper((int)(unsigned char) *cptr)) - gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line); - }; - 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_print_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; -/* - * Do nothing if there is no line to be redisplayed. - */ - if(gl->endline) - return 0; -/* - * Erase the current input line. - */ - if(gl_erase_line(gl)) - 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_print_string(gl, gl->line, '\0')) - return 1; -/* - * Restore the cursor position. - */ - if(gl_place_cursor(gl, buff_curpos)) - return 1; -/* - * Mark the redisplay operation as having been completed. - */ - gl->redisplay = 0; -/* - * 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) -{ -/* - * Home the cursor and clear from there to the end of the display. - */ - if(gl_print_control_sequence(gl, gl->nline, gl->home) || - gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * The input line is no longer displayed. - */ - gl_line_erased(gl); -/* - * Arrange for the input line to be redisplayed. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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_buffer_char(gl, swap[0], gl->buff_curpos); - gl_buffer_char(gl, swap[1], gl->buff_curpos+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_print_char(gl, swap[0], swap[1]) || - gl_print_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_print_string(gl, gl->line + gl->buff_curpos, '\0') || - gl_truncate_display(gl)) - 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,NULL)) - 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, NULL); -/* - * 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, NULL)) - 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, NULL); -/* - * 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, NULL)) - 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; -} - -/*....................................................................... - * Attempt to ask the terminal for its current size. On systems that - * don't support the TIOCWINSZ ioctl() for querying the terminal size, - * the current values of gl->ncolumn and gl->nrow are returned. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * ncolumn int * The number of columns will be assigned to *ncolumn. - * nline int * The number of lines will be assigned to *nline. - */ -static void gl_query_size(GetLine *gl, int *ncolumn, int *nline) -{ -#ifdef TIOCGWINSZ -/* - * Query the new terminal window size. Ignore invalid responses. - */ - struct winsize size; - if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 && - size.ws_row > 0 && size.ws_col > 0) { - *ncolumn = size.ws_col; - *nline = size.ws_row; - return; - }; -#endif -/* - * Return the existing values. - */ - *ncolumn = gl->ncolumn; - *nline = gl->nline; - return; -} - -/*....................................................................... - * Query the size of the terminal, and if it has changed, redraw the - * current input line accordingly. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _gl_update_size(GetLine *gl) -{ - int ncolumn, nline; /* The new size of the terminal */ -/* - * Query the new terminal window size. - */ - gl_query_size(gl, &ncolumn, &nline); -/* - * Update gl and the displayed line to fit the new dimensions. - */ - return gl_handle_tty_resize(gl, ncolumn, nline); -} - -/*....................................................................... - * Redraw the current input line to account for a change in the terminal - * size. Also install the new size in gl. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * ncolumn int The new number of columns. - * nline int The new number of lines. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline) -{ -/* - * If the input device isn't a terminal, just record the new size. - */ - if(!gl->is_term) { - gl->nline = nline; - gl->ncolumn = ncolumn; -/* - * Has the size actually changed? - */ - } else if(ncolumn != gl->ncolumn || nline != gl->nline) { -/* - * If we are currently editing a line, erase it. - */ - if(gl_erase_line(gl)) - return 1; -/* - * Update the recorded window size. - */ - gl->nline = nline; - gl->ncolumn = ncolumn; -/* - * Arrange for the input line to be redrawn before the next character - * is read from the terminal. - */ - gl_queue_redisplay(gl); - }; - return 0; -} - -/*....................................................................... - * 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; -/* - * Record the key sequence number of this search action. - */ - gl->last_search = gl->keyseq_count; -/* - * We don't want a search prefix for this function. - */ - if(_glh_search_prefix(gl->glh, gl->line, 0)) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - 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+1) == NULL) - return 0; - while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1)) - ; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = gl->ntotal; -/* - * Erase and display the new line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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); -/* - * Record the key sequence number of this search action. - */ - gl->last_search = gl->keyseq_count; -/* - * 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+1); - gl->preload_id = 0; - } else { -/* - * We don't want a search prefix for this function. - */ - if(_glh_search_prefix(gl->glh, gl->line, 0)) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - 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+1) == NULL) - return 0; - while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1)) - ; - }; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = gl->ntotal; -/* - * Erase and display the new line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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; -/* - * Record the key sequence number of this search action. - */ - gl->last_search = gl->keyseq_count; -/* - * If a prefix search isn't already in progress, replace the search - * prefix 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 keep the previous search prefix regardless, so as to force - * a repeat search even if the last command wasn't a history command. - */ - if(count >= 0 && !_glh_search_active(gl->glh) && - _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + - (gl->editor==GL_VI_MODE && gl->ntotal>0))) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - return 1; - }; -/* - * 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+1) == NULL) - return 0; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = gl->ntotal; -/* - * Erase and display the new line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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, NULL); -} - -/*....................................................................... - * 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); -/* - * Record the key sequence number of this search action. - */ - gl->last_search = gl->keyseq_count; -/* - * If a prefix search isn't already in progress, replace the search - * prefix 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 keep the previous search prefix regardless, so as to force - * a repeat search even if the last command wasn't a history command. - */ - if(count >= 0 && !_glh_search_active(gl->glh) && - _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + - (gl->editor==GL_VI_MODE && gl->ntotal>0))) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - return 1; - }; -/* - * Search forwards for the next matching line. - */ - if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL) - return 0; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * Arrange for the cursor to be placed at the end of the new line. - */ - gl->buff_curpos = gl->ntotal; -/* - * Erase and display the new line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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, NULL); -} - -#ifdef HIDE_FILE_SYSTEM -/*....................................................................... - * The following function is used as the default completion handler when - * the filesystem is to be hidden. It simply reports no completions. - */ -static CPL_MATCH_FN(gl_no_completions) -{ - return 0; -} -#endif - -/*....................................................................... - * This is the tab completion function that completes the filename that - * precedes the cursor position. Its callback data argument must be a - * pointer to a GlCplCallback containing the completion callback function - * and its callback data, or NULL to use the builtin filename completer. - */ -static KT_KEY_FN(gl_complete_word) -{ - CplMatches *matches; /* The possible completions */ - 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. */ - int waserr = 0; /* True after errors */ -/* - * Get the container of the completion callback and its callback data. - */ - GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn; -/* - * In vi command mode, switch to append mode so that the character under - * the cursor 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, NULL)) - 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, cb->data, - cb->fn); -/* - * No matching completions? - */ - if(!matches) { - waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO); -/* - * 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(_gl_normal_io(gl) || - _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn)) - waserr = 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, NULL)) - waserr = 1; - }; -/* - * Work out the number of characters that are to be added. - */ - nextra = suffix_len + cont_len; -/* - * Is there anything to be added? - */ - if(!waserr && 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. - */ - gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra); -/* - * Insert the filename extension. - */ - gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos); -/* - * Add the terminating characters. - */ - gl_buffer_string(gl, matches->cont_suffix, cont_len, - gl->buff_curpos + suffix_len); -/* - * Place the cursor position at the end of the completion. - */ - gl->buff_curpos += nextra; -/* - * 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(gl->displayed) { - if(gl_truncate_display(gl) || - gl_print_string(gl, gl->line + buff_pos, '\0') || - gl_place_cursor(gl, gl->buff_curpos)) - waserr = 1; - }; - } else { - (void) gl_print_info(gl, - "Insufficient room in line for file completion.", - GL_END_INFO); - waserr = 1; - }; - }; - }; -/* - * If any output had to be written to the terminal, then editing will - * have been suspended, make sure that we are back in raw line editing - * mode before returning. - */ - if(_gl_raw_io(gl, 1)) - waserr = 1; - return 0; -} - -#ifndef HIDE_FILE_SYSTEM -/*....................................................................... - * 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 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 under - * the cursor 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, NULL)) - return 1; -/* - * Locate the start of the filename that precedes the cursor position. - */ - start_path = _pu_start_of_path(gl->line, gl->buff_curpos); - 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. - */ - if(!result) - return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); -/* - * If no files matched, report this as well. - */ - if(result->nfile == 0 || !result->exists) - return gl_print_info(gl, "No files match.", GL_END_INFO); -/* - * 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) { - return gl_print_info(gl, "Insufficient room in line for file expansion.", - GL_END_INFO); - } else { -/* - * Do we need to move the part of the line that followed the unexpanded - * filename? - */ - if(nextra > 0) { - gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra); - } else if(nextra < 0) { - gl->buff_curpos += nextra; - gl_remove_from_buffer(gl, gl->buff_curpos, -nextra); - }; -/* - * 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_buffer_char(gl, '\\', j++); - }; - gl_buffer_char(gl, c, j++); - }; - gl_buffer_char(gl, ' ', j++); - }; - }; -/* - * Redisplay the part of the line which follows the start of - * the original filename. - */ - if(gl_place_cursor(gl, start_path - gl->line) || - gl_truncate_display(gl) || - gl_print_string(gl, start_path, start_path[length])) - return 1; -/* - * Move the cursor to the end of the expansion. - */ - return gl_place_cursor(gl, (start_path - gl->line) + length); -} -#endif - -#ifndef HIDE_FILE_SYSTEM -/*....................................................................... - * 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); - 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 it. - */ - if(!result) { - return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); -/* - * If no files matched, report this as well. - */ - } else if(result->nfile == 0 || !result->exists) { - return gl_print_info(gl, "No files match.", GL_END_INFO); -/* - * List the matching expansions. - */ - } else if(gl->echo) { - if(gl_start_newline(gl, 1) || - _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn)) - return 1; - gl_queue_redisplay(gl); - }; - return 0; -} -#endif - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ -/* - * Check the arguments. - */ - if(!gl || !match_fn) { - if(gl) - _err_record_msg(gl->err, "NULL argument", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Record the new completion function and its callback data. - */ - gl->cplfn.fn = match_fn; - gl->cplfn.data = data; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_change_terminal() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_change_terminal(gl, input_fp, output_fp, term); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_change_terminal() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static 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) { - gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).", - GL_END_INFO); - return 1; - }; -/* - * Are we displacing an existing terminal (as opposed to setting the - * initial terminal)? - */ - if(gl->input_fd >= 0) { -/* - * Make sure to leave the previous terminal in a usable state. - */ - if(_gl_normal_io(gl)) - return 1; -/* - * Remove the displaced terminal from the list of fds to watch. - */ -#ifdef HAVE_SELECT - 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); -/* - * If needed, expand the record of the maximum file-descriptor that might - * need to be monitored with select(). - */ -#ifdef HAVE_SELECT - 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. If the user - * sets the TERM environment variable to "dumb", treat a terminal as - * a non-interactive I/O stream. - */ - is_term = (isatty(gl->input_fd) && isatty(gl->output_fd)) && - !(term && strcmp(term, "dumb")==0); -/* - * 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)) { - _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); - return 1; - }; -/* - * If we don't set this now, gl_control_strings() won't know - * that it is talking to a terminal. - */ - gl->is_term = 1; -/* - * Lookup the terminal control string and size information. - */ - if(gl_control_strings(gl, term)) { - gl->is_term = 0; - return 1; - }; -/* - * Bind terminal-specific keys. - */ - if(gl_bind_terminal_keys(gl)) - return 1; - }; -/* - * Assume that the caller has given us a terminal in a sane state. - */ - gl->io_mode = GL_NORMAL_MODE; -/* - * Switch into the currently configured I/O mode. - */ - if(_gl_io_mode(gl, gl->io_mode)) - 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")) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - 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) { - gl_record_status(gl, GLR_EOF, 0); - return 1; -/* - * If we are at the end of the line list possible completions. - */ - } else if(gl->buff_curpos >= gl->ntotal) { - return gl_list_completions(gl, 1, NULL); -/* - * 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, NULL); - }; -} - -/*....................................................................... - * 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) { - gl_record_status(gl, GLR_EOF, 0); - return 1; -/* - * Otherwise list possible completions. - */ - } else { - return gl_list_completions(gl, 1, NULL); - }; -} - -/*....................................................................... - * List possible completions of the word that precedes the cursor. The - * callback data argument must either be NULL to select the default - * file completion callback, or be a GlCplCallback object containing the - * completion callback function to call. - */ -static KT_KEY_FN(gl_list_completions) -{ - int waserr = 0; /* True after errors */ -/* - * Get the container of the completion callback and its callback data. - */ - GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn; -/* - * Get the list of possible completions. - */ - CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, - cb->data, cb->fn); -/* - * No matching completions? - */ - if(!matches) { - waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO); -/* - * List the matches. - */ - } else if(matches->nmatch > 0 && gl->echo) { - if(_gl_normal_io(gl) || - _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn)) - waserr = 1; - }; -/* - * If any output had to be written to the terminal, then editing will - * have been suspended, make sure that we are back in raw line editing - * mode before returning. - */ - if(_gl_raw_io(gl, 1)) - waserr = 1; - return waserr; -} - -/*....................................................................... - * 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, "up", gl->u_arrow, "^[[A", "^[OA") || - _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") || - _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") || - _gl_rebind_arrow_key(gl, "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: - * gl GetLine * The resource object of gl_get_line(). - * 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(GetLine *gl, const char *name, - const char *term_seq, const char *def_seq1, - const char *def_seq2) -{ - KeySym *keysym; /* The binding-table entry matching the arrow-key name */ - int nsym; /* The number of ambiguous matches */ -/* - * 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(gl->bindings, name, strlen(name), &keysym, &nsym) - == KT_EXACT_MATCH) { -/* - * Get the action function. - */ - KtAction *action = keysym->actions + keysym->binder; - KtKeyFn *fn = action->fn; - void *data = action->data; -/* - * Bind this to each of the specified key sequences. - */ - if((term_seq && - _kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) || - (def_seq1 && - _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) || - (def_seq2 && - _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - 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) -{ -/* - * If filesystem access is to be excluded, configuration files can't - * be read. - */ -#ifdef WITHOUT_FILE_SYSTEM - _err_record_msg(gl->err, - "Can't read configuration files without filesystem access", - END_ERR_MSG); - errno = EINVAL; - return 1; -#else - 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) { - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Expand the filename. - */ - expansion = ef_expand_file(gl->ef, filename, -1); - if(!expansion) { - gl_print_info(gl, "Unable to expand ", filename, " (", - ef_last_error(gl->ef), ").", GL_END_INFO); - 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; -#endif -} - -/*....................................................................... - * 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) { - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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) { - gl_report_config_error(gl, origin, *lineno, "Too many arguments."); - 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) { - gl_report_config_error(gl, origin, *lineno, "Line too long."); - 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)) { - gl_report_config_error(gl, origin, *lineno, - _kt_last_error(gl->bindings)); - }; - break; - default: - gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments."); - }; - } 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 { - gl_report_config_error(gl, origin, *lineno, - "The argument of editor should be vi or emacs."); - }; - } else if(strcmp(argv[0], "nobeep") == 0) { - gl->silence_bell = 1; - } else { - gl_report_config_error(gl, origin, *lineno, "Unknown command name."); - }; -/* - * Skip any trailing comment. - */ - while(c != '\n' && c != EOF) - c = getc_fn(stream); - (*lineno)++; - return 0; -} - -/*....................................................................... - * This is a private function of _gl_parse_config_line() which prints - * out an error message about the contents of the line, prefixed by the - * name of the origin of the line and its line number. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * origin const char * The name of the entity being read (eg. a - * file name). - * lineno int The line number at which the error occurred. - * errmsg const char * The error message. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_report_config_error(GetLine *gl, const char *origin, int lineno, - const char *errmsg) -{ - char lnum[20]; /* A buffer in which to render a single integer */ -/* - * Convert the line number into a string. - */ - sprintf(lnum, "%d", lineno); -/* - * Have the string printed on the terminal. - */ - return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO); -} - -/*....................................................................... - * 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; -} - -#ifndef HIDE_FILE_SYSTEM -/*....................................................................... - * 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 */ -/* - * Locate the start of the filename that precedes the cursor position. - */ - start_path = _pu_start_of_path(gl->line, gl->buff_curpos); - 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. - */ - if(!result) { - return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); -/* - * If no files matched, report this as well. - */ - } else if(result->nfile == 0 || !result->exists) { - return gl_print_info(gl, "No files match.", GL_END_INFO); -/* - * Complain if more than one file matches. - */ - } else if(result->nfile > 1) { - return gl_print_info(gl, "More than one file matches.", GL_END_INFO); -/* - * 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])) { - return gl_print_info(gl, "Not a normal file.", GL_END_INFO); - } else { -/* - * Attempt to open and install the specified file for reading. - */ - gl->file_fp = fopen(result->files[0], "r"); - if(!gl->file_fp) { - return gl_print_info(gl, "Unable to open: ", result->files[0], - GL_END_INFO); - }; -/* - * If needed, expand the record of the maximum file-descriptor that might - * need to be monitored with select(). - */ -#ifdef HAVE_SELECT - if(fileno(gl->file_fp) > gl->max_fd) - gl->max_fd = fileno(gl->file_fp); -#endif -/* - * Is non-blocking I/O needed? - */ - if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE && - gl_nonblocking_io(gl, fileno(gl->file_fp))) { - gl_revert_input(gl); - return gl_print_info(gl, "Can't read file %s with non-blocking I/O", - result->files[0]); - }; -/* - * Inform the user what is happening. - */ - if(gl_print_info(gl, "<Taking input from ", result->files[0], ">", - GL_END_INFO)) - return 1; - }; - return 0; -} -#endif - -/*....................................................................... - * 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; - gl->endline = 1; -} - -/*....................................................................... - * 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; -/* - * Record the key sequence number of this search action. - */ - gl->last_search = gl->keyseq_count; -/* - * Recall the next oldest line in the history list. - */ - if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL) - return 0; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = gl->ntotal; -/* - * Erase and display the new line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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; -/* - * Record the key sequence number of this search action. - */ - gl->last_search = gl->keyseq_count; -/* - * Recall the next oldest line in the history list. - */ - if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL) - return 0; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = gl->ntotal; -/* - * Erase and display the new line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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, NULL); -/* - * 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 - Either an error occured, or the output - * blocked and non-blocking I/O is being used. - * See gl->rtn_status for details. - */ -static int gl_flush_output(GetLine *gl) -{ -/* - * Record the fact that we are about to write to the terminal. - */ - gl->pending_io = GLP_WRITE; -/* - * Attempt to flush the output to the terminal. - */ - errno = 0; - switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) { - case GLQ_FLUSH_DONE: - return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL); - break; - case GLQ_FLUSH_AGAIN: /* Output blocked */ - gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); - return 1; - break; - default: /* Abort the line if an error occurs */ - gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno); - return 1; - break; - }; -} - -/*....................................................................... - * This is the callback which _glq_flush_queue() uses to write buffered - * characters to the terminal. - */ -static GL_WRITE_FN(gl_flush_terminal) -{ - int ndone = 0; /* The number of characters written so far */ -/* - * Get the line-editor resource object. - */ - GetLine *gl = (GetLine *) data; -/* - * Transfer the latest array of characters to stdio. - */ - while(ndone < n) { - int nnew = write(gl->output_fd, s, n-ndone); -/* - * If the write was successful, add to the recorded number of bytes - * that have now been written. - */ - if(nnew > 0) { - ndone += nnew; -/* - * If a signal interrupted the call, restart the write(), since all of - * the signals that gl_get_line() has been told to watch for are - * currently blocked. - */ - } else if(errno == EINTR) { - continue; -/* - * If we managed to write something before an I/O error occurred, or - * output blocked before anything was written, report the number of - * bytes that were successfully written before this happened. - */ - } else if(ndone > 0 -#if defined(EAGAIN) - || errno==EAGAIN -#endif -#if defined(EWOULDBLOCK) - || errno==EWOULDBLOCK -#endif - ) { - return ndone; - -/* - * To get here, an error must have occurred before anything new could - * be written. - */ - } else { - return -1; - }; - }; -/* - * To get here, we must have successfully written the number of - * bytes that was specified. - */ - return n; -} - -/*....................................................................... - * 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: - _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG); - errno = EINVAL; - 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)) - gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line); - else if(isupper((int)(unsigned char) *cptr)) - gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line); -/* - * 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_print_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, NULL) || - gl_vi_insert(gl, 0, NULL); - -} - -/*....................................................................... - * 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, NULL) || - gl_vi_insert(gl, 0, NULL); -} - -/*....................................................................... - * 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, NULL) || - gl_vi_insert(gl, 0, NULL); -} - -/*....................................................................... - * 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_terminal(gl, 1, &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, NULL) || gl_vi_insert(gl, 0, NULL); -} - -/*....................................................................... - * 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,NULL) || gl_vi_insert(gl,0,NULL); -} - -/*....................................................................... - * 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,NULL) || gl_vi_insert(gl,0,NULL); -} - -/*....................................................................... - * 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, NULL); - else - return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL); -} - -/*....................................................................... - * 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, NULL); - else - return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL); - }; - 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_terminal(gl, 1, &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, NULL); - 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->prompt_len + - gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len)); -} - -/*....................................................................... - * 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_action.fn != gl_vi_repeat_change) { - gl->vi.repeat.action = gl->current_action; - 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'; - }; -/* - * Record the length of the stored string. - */ - gl->vi.undo.ntotal = gl->ntotal; -/* - * Accomodate the new contents of gl->line[]. - */ - gl_update_buffer(gl); -/* - * 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.action.fn = gl_vi_undo; - gl->vi.repeat.action.data = NULL; - gl->vi.repeat.count = 1; -/* - * Display the restored line. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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, NULL) || gl_vi_insert(gl, 0, NULL); -} - -/*....................................................................... - * 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, NULL) || gl_vi_insert(gl, 0, NULL); -} - -/*....................................................................... - * 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, NULL); -} - -/*....................................................................... - * 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, NULL) || gl_vi_insert(gl, 0, NULL); -} - -/*....................................................................... - * 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, NULL); - else - return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL); -} - -/*....................................................................... - * 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, NULL); - else - return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1, - NULL); - }; - 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, NULL); /* Vi moves 1 left 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_print_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.action.fn) - return gl_ring_bell(gl, 1, NULL); -/* - * 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.action.fn(gl, gl->vi.repeat.count, - gl->vi.repeat.action.data); -/* - * 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, NULL); - 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) -{ - 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 editing 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) { - gl_discard_chars(gl, 1); - if(gl->ntotal >= gl->linelen) - return 0; - if(c == '\n' || c == '\r') - return gl_newline(gl, 1, NULL); - gl_buffer_char(gl, c, gl->ntotal); - 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)) { - gl_discard_chars(gl, 1); - return gl_digit_argument(gl, c, NULL); -/* - * 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) { - KtAction *action; /* An action function */ - KeySym *keysym; /* The symbol-table entry of a key-sequence */ - int nsym; /* The number of ambiguously matching key-sequences */ -/* - * 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, &keysym, &nsym)) { - case KT_EXACT_MATCH: -/* - * Get the matching action function. - */ - action = keysym->actions + keysym->binder; -/* - * Get the repeat count, passing the last keystroke if executing the - * digit-argument action. - */ - if(action->fn == gl_digit_argument) { - count = c; - } else { - count = gl->number >= 0 ? gl->number : 1; - }; -/* - * Record the function that is being invoked. - */ - gl->current_action = *action; - 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 = action->fn(gl, count, action->data); -/* - * In server mode, the action will return immediately if it tries to - * read input from the terminal, and no input is currently available. - * If this happens, abort. Note that gl_get_input_line() will rewind - * the read-ahead buffer to allow the next call to redo the function - * from scratch. - */ - if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ) - return 1; -/* - * Discard the now processed characters from the key sequence buffer. - */ - gl_discard_chars(gl, gl->nread); -/* - * If the latest action function wasn't a history action, cancel any - * current history search. - */ - if(gl->last_search != gl->keyseq_count) - _glh_cancel_search(gl->glh); -/* - * Reset the repeat count after running action functions. - */ - if(action->fn != gl_digit_argument) - gl->number = -1; - return ret ? 1 : 0; - break; - case KT_AMBIG_MATCH: /* Ambiguous match - so read the next character */ - if(gl_read_terminal(gl, 1, &c)) - 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, 1, NULL); - } 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; - }; - gl_discard_chars(gl, 1); - _glh_cancel_search(gl->glh); - return 0; - break; - case KT_BAD_MATCH: - gl_ring_bell(gl, 1, NULL); - gl_discard_chars(gl, gl->nread); - _glh_cancel_search(gl->glh); - return 1; - break; - }; - }; -/* - * If the key sequence was too long to match, ring the bell, then - * discard the first character, so that the next attempt to match a - * key-sequence continues with the next key press. In practice this - * shouldn't happen, since one isn't allowed to bind action functions - * to keysequences that are longer than GL_KEY_MAX. - */ - gl_ring_bell(gl, 1, NULL); - gl_discard_chars(gl, 1); - 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 gl_get_line(), 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_configure_getline() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_configure_getline(gl, app_string, app_file, user_file); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_configure_getline() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_configure_getline(GetLine *gl, const char *app_string, - const char *app_file, const char *user_file) -{ -/* - * 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)) { - errno = ENOMEM; - _err_record_msg(gl->err, - "Insufficient memory to record tecla configuration file names", - END_ERR_MSG); - 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; -} - -#ifndef HIDE_FILE_SYSTEM -/*....................................................................... - * 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); -} -#endif - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_save_history() */ -/* - * Check the arguments. - */ - if(!gl || !filename || !comment) { - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_save_history(gl, filename, comment, max_lines); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_save_history() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_save_history(GetLine *gl, const char *filename, - const char *comment, int max_lines) -{ -/* - * If filesystem access is to be excluded, then history files can't - * be written. - */ -#ifdef WITHOUT_FILE_SYSTEM - _err_record_msg(gl->err, "Can't save history without filesystem access", - END_ERR_MSG); - errno = EINVAL; - return 1; -#else - FileExpansion *expansion; /* The expansion of the filename */ -/* - * Expand the filename. - */ - expansion = ef_expand_file(gl->ef, filename, -1); - if(!expansion) { - gl_print_info(gl, "Unable to expand ", filename, " (", - ef_last_error(gl->ef), ").", GL_END_INFO); - return 1; - }; -/* - * Attempt to save to the specified file. - */ - if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - return 1; - }; - return 0; -#endif -} - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_load_history() */ -/* - * Check the arguments. - */ - if(!gl || !filename || !comment) { - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_load_history(gl, filename, comment); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_load_history() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_load_history(GetLine *gl, const char *filename, - const char *comment) -{ -/* - * If filesystem access is to be excluded, then history files can't - * be read. - */ -#ifdef WITHOUT_FILE_SYSTEM - _err_record_msg(gl->err, "Can't load history without filesystem access", - END_ERR_MSG); - errno = EINVAL; - return 1; -#else - FileExpansion *expansion; /* The expansion of the filename */ -/* - * Expand the filename. - */ - expansion = ef_expand_file(gl->ef, filename, -1); - if(!expansion) { - gl_print_info(gl, "Unable to expand ", filename, " (", - ef_last_error(gl->ef), ").", GL_END_INFO); - return 1; - }; -/* - * Attempt to load from the specified file. - */ - if(_glh_load_history(gl->glh, expansion->files[0], comment, - gl->cutbuf, gl->linelen+1)) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - gl->cutbuf[0] = '\0'; - return 1; - }; - gl->cutbuf[0] = '\0'; - return 0; -#endif -} - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_watch_fd() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; - if(fd < 0) { - _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_watch_fd(gl, fd, event, callback, data); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_watch_fd() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static 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 */ -/* - * 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) { - errno = ENOMEM; - _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG); - 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; -} -#endif - -/*....................................................................... - * On systems with the select() system call, the gl_inactivity_timeout() - * function provides the option of setting (or cancelling) an - * inactivity timeout. Inactivity, in this case, refers both to - * terminal input received from the user, and to I/O on any file - * descriptors registered by calls to gl_watch_fd(). If at any time, - * no activity is seen for the requested time period, the specified - * timeout callback function is called. On returning, this callback - * returns a code which tells gl_get_line() what to do next. Note that - * each call to gl_inactivity_timeout() replaces any previously installed - * timeout callback, and that specifying a callback of 0, turns off - * inactivity timing. - * - * Beware that although the timeout argument includes a nano-second - * component, few computer clocks presently have resolutions finer - * than a few milliseconds, so asking for less than a few milliseconds - * is equivalent to zero on a lot of systems. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * callback GlTimeoutFn * The function to call when the inactivity - * timeout is exceeded. To turn off - * inactivity timeouts altogether, send 0. - * data void * A pointer to arbitrary data to pass to the - * callback function. - * sec unsigned long The number of whole seconds in the timeout. - * nsec unsigned long The fractional number of seconds in the - * timeout, expressed in nano-seconds (see - * the caveat above). - * 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_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data, - unsigned long sec, unsigned long nsec) -#if !defined(HAVE_SELECT) -{return 1;} /* The facility isn't supported on this system */ -#else -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Install a new timeout? - */ - if(timeout_fn) { - gl->timer.dt.tv_sec = sec; - gl->timer.dt.tv_usec = nsec / 1000; - gl->timer.fn = timeout_fn; - gl->timer.data = data; - } else { - gl->timer.fn = 0; - gl->timer.data = NULL; - }; -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return 0; -} -#endif - -/*....................................................................... - * When select() is available, this is a private function of - * gl_read_input() which responds to file-descriptor events registered by - * the caller. Note that it assumes that it is being called from within - * gl_read_input()'s sigsetjump() clause. - * - * Input: - * gl GetLine * The resource object of this module. - * fd int The file descriptor to be watched for user input. - * Output: - * return int 0 - OK. - * 1 - An error occurred. - */ -static int gl_event_handler(GetLine *gl, int fd) -#if !defined(HAVE_SELECT) -{return 0;} -#else -{ -/* - * Set up a zero-second timeout. - */ - struct timeval zero; - zero.tv_sec = zero.tv_usec = 0; -/* - * 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 || gl->timer.fn) { - int nready; /* The number of file descriptors that are ready for I/O */ -/* - * Get the set of descriptors to be watched. - */ - fd_set rfds = gl->rfds; - fd_set wfds = gl->wfds; - fd_set ufds = gl->ufds; -/* - * Get the appropriate timeout. - */ - struct timeval dt = gl->timer.fn ? gl->timer.dt : zero; -/* - * Add the specified user-input file descriptor tot he set that is to - * be watched. - */ - FD_SET(fd, &rfds); -/* - * Unblock the signals that we are watching, while select is blocked - * waiting for I/O. - */ - gl_catch_signals(gl); -/* - * Wait for activity on any of the file descriptors. - */ - nready = select(gl->max_fd+1, &rfds, &wfds, &ufds, - (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL); -/* - * 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 before executing callback functions. Note that - * the caller will unblock them again when it needs to, so there is - * no need to undo this before returning. - */ - gl_mask_signals(gl, NULL); -/* - * If select() returns but none of the file descriptors are reported - * to have activity, then select() timed out. - */ - if(nready == 0) { -/* - * Note that in non-blocking server mode, the inactivity timer is used - * to allow I/O to block for a specified amount of time, so in this - * mode we return the postponed blocked status when an abort is - * requested. - */ - if(gl_call_timeout_handler(gl)) { - return 1; - } else if(gl->io_mode == GL_SERVER_MODE) { - gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); - return 1; - }; -/* - * If nready < 0, this means an error occurred. - */ - } else if(nready < 0) { - if(errno != EINTR) { - gl_record_status(gl, GLR_ERROR, errno); - return 1; - }; -/* - * If the user-input file descriptor has data available, return. - */ - } else if(FD_ISSET(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, &wfds)) { - if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE)) - return 1; - break; /* The callback may have changed the list of nodes */ - }; - }; - }; -/* - * Just in case the above event handlers asked for the input line to - * be redrawn, flush any pending output. - */ - if(gl_flush_output(gl)) - return 1; - }; - return 0; -} -#endif - -#if defined(HAVE_SELECT) -/*....................................................................... - * 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 waserr = 0; /* True after any error */ -/* - * 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)) { - _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); - return 1; - }; - attr.c_oflag |= OPOST; - while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { - if(errno != EINTR) { - _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); - return 1; - }; - }; -/* - * Invoke the application's callback function. - */ - switch(gfh->fn(gl, gfh->data, fd, event)) { - default: - case GLFD_ABORT: - gl_record_status(gl, GLR_FDABORT, 0); - waserr = 1; - break; - case GLFD_REFRESH: - gl_queue_redisplay(gl); - break; - case GLFD_CONTINUE: - break; - }; -/* - * If the callback function called gl_normal_io(), restore raw mode, - * and queue a redisplay of the input line. - */ - if(!gl->raw_mode) - waserr = waserr || _gl_raw_io(gl, 1); -/* - * Disable conversion of newline characters to carriage-return/linefeed. - */ - attr.c_oflag &= ~(OPOST); - while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { - if(errno != EINTR) { - _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); - return 1; - }; - }; - return waserr; -} - -/*....................................................................... - * This is a private function of gl_event_handler(), used to call a - * inactivity timer callbacks. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_call_timeout_handler(GetLine *gl) -{ - Termios attr; /* The terminal attributes */ - int waserr = 0; /* True after any error */ -/* - * Make sure that there is an inactivity timeout callback. - */ - if(!gl->timer.fn) - return 0; -/* - * 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)) { - _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); - return 1; - }; - attr.c_oflag |= OPOST; - while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { - if(errno != EINTR) { - _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); - return 1; - }; - }; -/* - * Invoke the application's callback function. - */ - switch(gl->timer.fn(gl, gl->timer.data)) { - default: - case GLTO_ABORT: - gl_record_status(gl, GLR_TIMEOUT, 0); - waserr = 1; - break; - case GLTO_REFRESH: - gl_queue_redisplay(gl); - break; - case GLTO_CONTINUE: - break; - }; -/* - * If the callback function called gl_normal_io(), restore raw mode, - * and queue a redisplay of the input line. - */ - if(!gl->raw_mode) - waserr = waserr || _gl_raw_io(gl, 1); -/* - * Disable conversion of newline characters to carriage-return/linefeed. - */ - attr.c_oflag &= ~(OPOST); - while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { - if(errno != EINTR) { - _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); - 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of this function */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals while we install the new configuration. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * If the group isn't being changed, do nothing. - */ - if(_glh_get_group(gl->glh) == id) { - status = 0; -/* - * Establish the new group. - */ - } else if(_glh_set_group(gl->glh, id)) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - status = 1; -/* - * Prevent history information from the previous group being - * inappropriately used by the next call to gl_get_line(). - */ - } else { - gl->preload_history = 0; - gl->last_search = -1; - status = 0; - }; -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of this function */ -/* - * Check the arguments. - */ - if(!gl || !fp || !fmt) { - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Display the specified history group(s) while signals are blocked. - */ - status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups, - max_lines) || fflush(fp)==EOF; - if(!status) - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * 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 object to be returned */ - sigset_t oldset; /* The signals that were blocked on entry */ - /* to this function */ -/* - * Block all signals while accessing gl. - */ - gl_mask_signals(gl, &oldset); -/* - * Lookup/configure the terminal size. - */ - _gl_terminal_size(gl, def_ncolumn, def_nline, &size); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - return size; -} - -/*....................................................................... - * This is the private body of the gl_terminal_size() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline, - GlTerminalSize *size) -{ - 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. - */ - gl_query_size(gl, &gl->ncolumn, &gl->nline); -/* - * If gl_query_size() couldn't ask the terminal, it will have - * left gl->nrow and gl->ncolumn unchanged. If these values haven't - * been changed from their initial values of zero, we need to find - * a different method to get the terminal size. - * - * If the number of lines isn't known yet, first see if the - * LINES environment ariable exists and specifies a believable number. - * If this doesn't work, look up the default size in the terminal - * information database. - */ - 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 the number of lines isn't known yet, first see if the COLUMNS - * environment ariable exists and specifies a believable number. If - * this doesn't work, look up the default size in the terminal - * information database. - */ - 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. - */ - if(size) { - size->nline = gl->nline; - size->ncolumn = gl->ncolumn; - }; - return; -} - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of this function */ -/* - * Check the arguments. - */ - if(!gl) - return 1; -/* - * Block all signals while modifying the contents of gl. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Perform the resize while signals are blocked. - */ - status = _glh_resize_history(gl->glh, bufsize); - if(status) - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Apply the limit while signals are blocked. - */ - _glh_limit_history(gl->glh, max_lines); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Clear the history buffer while signals are blocked. - */ - _glh_clear_history(gl->glh, all_groups); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Change the history recording mode while signals are blocked. - */ - _glh_toggle_history(gl->glh, enable); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of this function */ -/* - * Check the arguments. - */ - if(!gl) - return 0; -/* - * Block all signals while modifying the contents of gl. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Perform the lookup while signals are blocked. - */ - status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line, - &line->group, &line->timestamp); - if(status) - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Lookup the status while signals are blocked. - */ - _glh_state_of_history(gl->glh, &state->enabled, &state->group, - &state->max_lines); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Lookup the information while signals are blocked. - */ - _glh_range_of_history(gl->glh, &range->oldest, &range->newest, - &range->nlines); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Lookup the information while signals are blocked. - */ - _glh_size_of_history(gl->glh, &size->size, &size->used); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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(gl_start_newline(gl, 1)) - return 1; -/* - * List history lines that belong to the current group. - */ - _glh_show_history(gl->glh, gl_write_fn, gl, "%N %T %H\r\n", 0, - count<=1 ? -1 : count); -/* - * Arrange for the input line to be redisplayed. - */ - gl_queue_redisplay(gl); - return 0; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ - int was_echoing; /* The echoing disposition on entry to this function */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Install the new disposition while signals are blocked. - */ - was_echoing = gl->echo; - if(enable >= 0) - gl->echo = enable; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); -/* - * Return the original echoing disposition. - */ - 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_print_control_sequence(gl, 1, gl->bol)) - return 1; -/* - * Mark the line as partially displayed. - */ - gl->displayed = 1; -/* - * Write the prompt, using the currently selected prompt style. - */ - switch(gl->prompt_style) { - case GL_LITERAL_PROMPT: - if(gl_print_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_print_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_print_control_sequence(gl, 1, gl->bold)) - return 1; - if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) && - gl_print_control_sequence(gl, 1, gl->underline)) - return 1; - if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) && - gl_print_control_sequence(gl, 1, gl->standout)) - return 1; - if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) && - gl_print_control_sequence(gl, 1, gl->dim)) - return 1; - if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) && - gl_print_control_sequence(gl, 1, gl->reverse)) - return 1; - if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) && - gl_print_control_sequence(gl, 1, gl->blink)) - return 1; - old_attr = new_attr; - }; -/* - * Display the latest character. - */ - if(gl_print_char(gl, *pptr, pptr[1])) - return 1; - }; -/* - * Turn off all text attributes now that we have finished drawing - * the prompt. - */ - if(gl_print_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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Replace the prompt. - */ - _gl_replace_prompt(gl, prompt); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * This is the private body of the gl_replace_prompt() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static void _gl_replace_prompt(GetLine *gl, const char *prompt) -{ -/* - * Substitute an empty prompt? - */ - if(!prompt) - prompt = ""; -/* - * Gaurd against aliasing between prompt and gl->prompt. - */ - if(gl->prompt != prompt) { -/* - * Get the length of the new prompt string. - */ - size_t slen = strlen(prompt); -/* - * If needed, allocate a new buffer for the prompt string. - */ - if(!gl->prompt || slen > strlen(gl->prompt)) { - size_t size = sizeof(char) * (slen + 1); - char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size); - if(!new_prompt) - return; - gl->prompt = new_prompt; - }; -/* - * Make a copy of the new prompt. - */ - strcpy(gl->prompt, prompt); - }; -/* - * Record the statistics of the new prompt. - */ - gl->prompt_len = gl_displayed_prompt_width(gl); - gl->prompt_changed = 1; - gl_queue_redisplay(gl); - return; -} - -/*....................................................................... - * 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) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Install the new style in gl while signals are blocked. - */ - if(style != gl->prompt_style) { - gl->prompt_style = style; - gl->prompt_len = gl_displayed_prompt_width(gl); - gl->prompt_changed = 1; - gl_queue_redisplay(gl); - }; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; -} - -/*....................................................................... - * 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) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of this function */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals while modifying the contents of gl. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Perform the modification while signals are blocked. - */ - status = _gl_trap_signal(gl, signo, flags, after, errno_value); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_trap_signal() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value) -{ - GlSignalNode *sig; -/* - * Complain if an attempt is made to trap untrappable signals. - * These would otherwise cause errors later in gl_mask_signals(). - */ - if(0 -#ifdef SIGKILL - || signo==SIGKILL -#endif -#ifdef SIGBLOCK - || signo==SIGBLOCK -#endif - ) { - 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) { - _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG); - sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); - return 1; - }; -/* - * Add the signal to the bit-mask of signals being trapped. - */ - sigaddset(&gl->all_signal_set, signo); - }; -/* - * 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 */ - sigset_t oldset; /* The signals that were blocked on entry to this */ - /* function. */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals while modifying the contents of gl. - */ - if(gl_mask_signals(gl, &oldset)) - 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); -/* - * Remove the signal from the bit-mask union of signals being trapped. - */ - sigdelset(&gl->all_signal_set, signo); - }; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - 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. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_line_ended(GetLine *gl, int newline_char) -{ -/* - * If the newline character is printable, display it at the end of - * the line, and add it to the input line buffer. - */ - if(isprint((int)(unsigned char) newline_char)) { - if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char)) - return 1; - } else { -/* - * Otherwise just append a newline character to the input line buffer. - */ - newline_char = '\n'; - gl_buffer_char(gl, newline_char, gl->ntotal); - }; -/* - * Add the line to the history buffer if it was entered with a - * newline character. - */ - if(gl->echo && gl->automatic_history && newline_char=='\n') - (void) _gl_append_history(gl, gl->line); -/* - * Except when 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 && gl_start_newline(gl, 1)) - return 1; -/* - * Record the successful return status. - */ - gl_record_status(gl, GLR_NEWLINE, 0); -/* - * Attempt to flush any pending output. - */ - (void) gl_flush_output(gl); -/* - * The next call to gl_get_line() will write the prompt for a new line - * (or continue the above flush if incomplete), so if we manage to - * flush the terminal now, report that we are waiting to write to the - * terminal. - */ - gl->pending_io = GLP_WRITE; - 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(GetLine *gl) -{ - int signo = -1; /* The requested signal number */ - if(gl) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Access gl now that signals are blocked. - */ - signo = gl->last_signal; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; - return signo; -} - -/*....................................................................... - * Prepare to edit a new line. - * - * Input: - * gl GetLine * The resource object of this library. - * prompt char * The prompt to prefix the line with, or NULL to - * use the same prompt that was used by the previous - * line. - * 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_present_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos) -{ -/* - * Prepare the line-editing properties for a new editing session. - */ - gl_reset_editor(gl); -/* - * Record the new prompt and its displayed width. - */ - if(prompt) - _gl_replace_prompt(gl, prompt); -/* - * Reset the history search pointers. - */ - if(_glh_cancel_search(gl->glh)) { - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - return 1; - }; -/* - * If the previous line was entered via the repeat-history action, - * preload the specified history line. - */ - if(gl->preload_history) { - gl->preload_history = 0; - if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) { - gl_update_buffer(gl); /* Compute gl->ntotal etc.. */ - gl->buff_curpos = gl->ntotal; - } else { - gl_truncate_buffer(gl, 0); - }; - gl->preload_id = 0; -/* - * Present a specified initial line? - */ - } else if(start_line) { - char *cptr; /* A pointer into gl->line[] */ -/* - * Measure the length of the starting line. - */ - int start_len = strlen(start_line); -/* - * If the length of the line is greater than the available space, - * truncate it. - */ - if(start_len > gl->linelen) - start_len = gl->linelen; -/* - * Load the line into the buffer. - */ - if(start_line != gl->line) - gl_buffer_string(gl, start_line, start_len, 0); -/* - * 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--) - ; - gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal); -/* - * 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; - }; -/* - * Clear the input line? - */ - } else { - gl_truncate_buffer(gl, 0); - }; -/* - * Arrange for the line to be displayed by gl_flush_output(). - */ - gl_queue_redisplay(gl); -/* - * Update the display. - */ - return gl_flush_output(gl); -} - -/*....................................................................... - * Reset all line-editing parameters for a new editing session. Note - * that this does not empty the input line, since that would prevent a - * gl_get_line() caller from specifying the returned line buffer as - * the start_line argument of the next call to gl_get_line(). - * - * Input: - * gl GetLine * The line editor resource object. - */ -static void gl_reset_editor(GetLine *gl) -{ -/* - * Warning: Don't clear gl->line[] and gl->ntotal here (see above). - */ - gl->buff_curpos = 0; - gl->term_curpos = 0; - gl->term_len = 0; - gl->insert_curpos = 0; - gl->number = -1; - gl->displayed = 0; - gl->endline = 0; - gl->redisplay = 0; - gl->postpone = 0; - gl->nbuf = 0; - gl->nread = 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.action.fn = 0; - gl->vi.repeat.action.data = 0; - gl->last_signal = -1; -} - -/*....................................................................... - * Print an informational message to the terminal, after starting a new - * line. - * - * Input: - * gl GetLine * The line editor resource object. - * ... const char * Zero or more strings to be printed. - * ... void * The last argument must always be GL_END_INFO. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_print_info(GetLine *gl, ...) -{ - va_list ap; /* The variable argument list */ - const char *s; /* The string being printed */ - int waserr = 0; /* True after an error */ -/* - * Only display output when echoing is on. - */ - if(gl->echo) { -/* - * Skip to the start of the next empty line before displaying the message. - */ - if(gl_start_newline(gl, 1)) - return 1; -/* - * Display the list of provided messages. - */ - va_start(ap, gl); - while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO) - waserr = gl_print_raw_string(gl, 1, s, -1); - va_end(ap); -/* - * Start a newline. - */ - waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1); -/* - * Arrange for the input line to be redrawn. - */ - gl_queue_redisplay(gl); - }; - return waserr; -} - -/*....................................................................... - * Go to the start of the next empty line, ready to output miscellaneous - * text to the screen. - * - * Note that when async-signal safety is required, the 'buffered' - * argument must be 0. - * - * Input: - * gl GetLine * The line editor resource object. - * buffered int If true, used buffered I/O when writing to - * the terminal. Otherwise use async-signal-safe - * unbuffered I/O. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_start_newline(GetLine *gl, int buffered) -{ - int waserr = 0; /* True after any I/O error */ -/* - * Move the cursor to the start of the terminal line that follows the - * last line of the partially enterred line. In order that this - * function remain async-signal safe when write_fn is signal safe, we - * can't call our normal output functions, since they call tputs(), - * who's signal saftey isn't defined. Fortunately, we can simply use - * \r and \n to move the cursor to the right place. - */ - if(gl->displayed) { /* Is an input line currently displayed? */ -/* - * On which terminal lines are the cursor and the last character of the - * input line? - */ - int curs_line = gl->term_curpos / gl->ncolumn; - int last_line = gl->term_len / gl->ncolumn; -/* - * Move the cursor to the start of the line that follows the last - * terminal line that is occupied by the input line. - */ - for( ; curs_line < last_line + 1; curs_line++) - waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1); - waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1); -/* - * Mark the line as no longer displayed. - */ - gl_line_erased(gl); - }; - return waserr; -} - -/*....................................................................... - * The callback through which all terminal output is routed. - * This simply appends characters to a queue buffer, which is - * subsequently flushed to the output channel by gl_flush_output(). - * - * Input: - * data void * The pointer to a GetLine line editor resource object - * cast to (void *). - * s const char * The string to be written. - * n int The number of characters to write from s[]. - * Output: - * return int The number of characters written. This will always - * be equal to 'n' unless an error occurs. - */ -static GL_WRITE_FN(gl_write_fn) -{ - GetLine *gl = (GetLine *) data; - int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl); - if(ndone != n) - _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG); - return ndone; -} - -/*....................................................................... - * Ask gl_get_line() what caused it to return. - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return GlReturnStatus The return status of the last call to - * gl_get_line(). - */ -GlReturnStatus gl_return_status(GetLine *gl) -{ - GlReturnStatus rtn_status = GLR_ERROR; /* The requested status */ - if(gl) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Access gl while signals are blocked. - */ - rtn_status = gl->rtn_status; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; - return rtn_status; -} - -/*....................................................................... - * In non-blocking server-I/O mode, this function should be called - * from the application's external event loop to see what type of - * terminal I/O is being waited for by gl_get_line(), and thus what - * direction of I/O to wait for with select() or poll(). - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return GlPendingIO The type of pending I/O being waited for. - */ -GlPendingIO gl_pending_io(GetLine *gl) -{ - GlPendingIO pending_io = GLP_WRITE; /* The requested information */ - if(gl) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Access gl while signals are blocked. - */ - pending_io = gl->pending_io; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - }; - return pending_io; -} - -/*....................................................................... - * In server mode, this function configures the terminal for non-blocking - * raw terminal I/O. In normal I/O mode it does nothing. - * - * Callers of this function must be careful to trap all signals that - * terminate or suspend the program, and call gl_normal_io() - * from the corresponding signal handlers in order to restore the - * terminal to its original settings before the program is terminated - * or suspended. They should also trap the SIGCONT signal to detect - * when the program resumes, and ensure that its signal handler - * call gl_raw_io() to redisplay the line and resume editing. - * - * This function is async signal safe. - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_raw_io(GetLine *gl) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_raw_io() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Don't allow applications to switch into raw mode unless in server mode. - */ - if(gl->io_mode != GL_SERVER_MODE) { - _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode", - END_ERR_MSG); - errno = EPERM; - status = 1; - } else { -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_raw_io(gl, 1); - }; -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the public function, gl_raw_io(). - * It assumes that the caller has checked its arguments and blocked the - * delivery of signals. - * - * This function is async signal safe. - */ -static int _gl_raw_io(GetLine *gl, int redisplay) -{ -/* - * If we are already in the correct mode, do nothing. - */ - if(gl->raw_mode) - return 0; -/* - * Switch the terminal to raw mode. - */ - if(gl->is_term && gl_raw_terminal_mode(gl)) - return 1; -/* - * Switch to non-blocking I/O mode? - */ - if(gl->io_mode==GL_SERVER_MODE && - (gl_nonblocking_io(gl, gl->input_fd) || - gl_nonblocking_io(gl, gl->output_fd) || - (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) { - if(gl->is_term) - gl_restore_terminal_attributes(gl); - return 1; - }; -/* - * If an input line is being entered, arrange for it to be - * displayed. - */ - if(redisplay) { - gl->postpone = 0; - gl_queue_redisplay(gl); - }; - return 0; -} - -/*....................................................................... - * Restore the terminal to the state that it had when - * gl_raw_io() was last called. After calling - * gl_raw_io(), this function must be called before - * terminating or suspending the program, and before attempting other - * uses of the terminal from within the program. See gl_raw_io() - * for more details. - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_normal_io(GetLine *gl) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_normal_io() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_normal_io(gl); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the public function, gl_normal_io(). - * It assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_normal_io(GetLine *gl) -{ -/* - * If we are already in normal mode, do nothing. - */ - if(!gl->raw_mode) - return 0; -/* - * Postpone subsequent redisplays until after _gl_raw_io(gl, 1) - * is next called. - */ - gl->postpone = 1; -/* - * Switch back to blocking I/O. Note that this is essential to do - * here, because when using non-blocking I/O, the terminal output - * buffering code can't always make room for new output without calling - * malloc(), and a call to malloc() would mean that this function - * couldn't safely be called from signal handlers. - */ - if(gl->io_mode==GL_SERVER_MODE && - (gl_blocking_io(gl, gl->input_fd) || - gl_blocking_io(gl, gl->output_fd) || - (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp))))) - return 1; -/* - * Move the cursor to the next empty terminal line. Note that - * unbuffered I/O is requested, to ensure that gl_start_newline() be - * async-signal-safe. - */ - if(gl->is_term && gl_start_newline(gl, 0)) - return 1; -/* - * Switch the terminal to normal mode. - */ - if(gl->is_term && gl_restore_terminal_attributes(gl)) { -/* - * On error, revert to non-blocking I/O if needed, so that on failure - * we remain in raw mode. - */ - if(gl->io_mode==GL_SERVER_MODE) { - gl_nonblocking_io(gl, gl->input_fd); - gl_nonblocking_io(gl, gl->output_fd); - if(gl->file_fp) - gl_nonblocking_io(gl, fileno(gl->file_fp)); - }; - return 1; - }; - return 0; -} - -/*....................................................................... - * This function allows you to install an additional completion - * action, or to change the completion function of an existing - * one. This should be called before the first call to gl_get_line() - * so that the name of the action be defined before the user's - * configuration file is read. - * - * 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. - * list_only int If non-zero, install an action that only lists - * possible completions, rather than attempting - * to perform the completion. - * name const char * The name with which users can refer to the - * binding in tecla configuration files. - * keyseq const char * Either NULL, or a key sequence with which - * to invoke the binding. This should be - * specified in the same manner as key-sequences - * in tecla configuration files (eg. "M-^I"). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, - int list_only, const char *name, const char *keyseq) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_completion_action() */ -/* - * Check the arguments. - */ - if(!gl || !name || !match_fn) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Install the new action while signals are blocked. - */ - status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the public function, gl_completion_action(). - * It assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, - int list_only, const char *name, - const char *keyseq) -{ - KtKeyFn *current_fn; /* An existing action function */ - void *current_data; /* The action-function callback data */ -/* - * Which action function is desired? - */ - KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word; -/* - * Is there already an action of the specified name? - */ - if(_kt_lookup_action(gl->bindings, name, ¤t_fn, ¤t_data) == 0) { -/* - * If the action has the same type as the one being requested, - * simply change the contents of its GlCplCallback callback data. - */ - if(current_fn == action_fn) { - GlCplCallback *cb = (GlCplCallback *) current_data; - cb->fn = match_fn; - cb->data = data; - } else { - errno = EINVAL; - _err_record_msg(gl->err, - "Illegal attempt to change the type of an existing completion action", - END_ERR_MSG); - return 1; - }; -/* - * No existing action has the specified name. - */ - } else { -/* - * Allocate a new GlCplCallback callback object. - */ - GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem); - if(!cb) { - errno = ENOMEM; - _err_record_msg(gl->err, "Insufficient memory to add completion action", - END_ERR_MSG); - return 1; - }; -/* - * Record the completion callback data. - */ - cb->fn = match_fn; - cb->data = data; -/* - * Attempt to register the new action. - */ - if(_kt_set_action(gl->bindings, name, action_fn, cb)) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - _del_FreeListNode(gl->cpl_mem, (void *) cb); - return 1; - }; - }; -/* - * Bind the action to a given key-sequence? - */ - if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - return 1; - }; - return 0; -} - -/*....................................................................... - * Register an application-provided function as an action function. - * This should preferably be called before the first call to gl_get_line() - * so that the name of the action becomes defined before the user's - * configuration file is read. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * data void * Arbitrary application-specific callback - * data to be passed to the callback - * function, fn(). - * fn GlActionFn * The application-specific function that - * implements the action. This will be invoked - * whenever the user presses any - * key-sequence which is bound to this action. - * name const char * The name with which users can refer to the - * binding in tecla configuration files. - * keyseq const char * The key sequence with which to invoke - * the binding. This should be specified in the - * same manner as key-sequences in tecla - * configuration files (eg. "M-^I"). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_register_action(GetLine *gl, void *data, GlActionFn *fn, - const char *name, const char *keyseq) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_register_action() */ -/* - * Check the arguments. - */ - if(!gl || !name || !fn) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Install the new action while signals are blocked. - */ - status = _gl_register_action(gl, data, fn, name, keyseq); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the public function, gl_register_action(). - * It assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn, - const char *name, const char *keyseq) -{ - KtKeyFn *current_fn; /* An existing action function */ - void *current_data; /* The action-function callback data */ -/* - * Get the action function which actually runs the application-provided - * function. - */ - KtKeyFn *action_fn = gl_run_external_action; -/* - * Is there already an action of the specified name? - */ - if(_kt_lookup_action(gl->bindings, name, ¤t_fn, ¤t_data) == 0) { -/* - * If the action has the same type as the one being requested, - * simply change the contents of its GlCplCallback callback data. - */ - if(current_fn == action_fn) { - GlExternalAction *a = (GlExternalAction *) current_data; - a->fn = fn; - a->data = data; - } else { - errno = EINVAL; - _err_record_msg(gl->err, - "Illegal attempt to change the type of an existing action", - END_ERR_MSG); - return 1; - }; -/* - * No existing action has the specified name. - */ - } else { -/* - * Allocate a new GlCplCallback callback object. - */ - GlExternalAction *a = - (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem); - if(!a) { - errno = ENOMEM; - _err_record_msg(gl->err, "Insufficient memory to add completion action", - END_ERR_MSG); - return 1; - }; -/* - * Record the completion callback data. - */ - a->fn = fn; - a->data = data; -/* - * Attempt to register the new action. - */ - if(_kt_set_action(gl->bindings, name, action_fn, a)) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - _del_FreeListNode(gl->cpl_mem, (void *) a); - return 1; - }; - }; -/* - * Bind the action to a given key-sequence? - */ - if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - return 1; - }; - return 0; -} - -/*....................................................................... - * Invoke an action function previously registered by a call to - * gl_register_action(). - */ -static KT_KEY_FN(gl_run_external_action) -{ - GlAfterAction status; /* The return value of the action function */ -/* - * Get the container of the action function and associated callback data. - */ - GlExternalAction *a = (GlExternalAction *) data; -/* - * Invoke the action function. - */ - status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line); -/* - * If the callback took us out of raw (possibly non-blocking) input - * mode, restore this mode, and queue a redisplay of the input line. - */ - if(_gl_raw_io(gl, 1)) - return 1; -/* - * Finally, check to see what the action function wants us to do next. - */ - switch(status) { - default: - case GLA_ABORT: - gl_record_status(gl, GLR_ERROR, errno); - return 1; - break; - case GLA_RETURN: - return gl_newline(gl, 1, NULL); - break; - case GLA_CONTINUE: - break; - }; - return 0; -} - -/*....................................................................... - * In server-I/O mode the terminal is left in raw mode between calls - * to gl_get_line(), so it is necessary for the application to install - * terminal restoring signal handlers for signals that could terminate - * or suspend the process, plus a terminal reconfiguration handler to - * be called when a process resumption signal is received, and finally - * a handler to be called when a terminal-resize signal is received. - * - * Since there are many signals that by default terminate or suspend - * processes, and different systems support different sub-sets of - * these signals, this function provides a convenient wrapper around - * sigaction() for assigning the specified handlers to all appropriate - * signals. It also arranges that when any one of these signals is - * being handled, all other catchable signals are blocked. This is - * necessary so that the specified signal handlers can safely call - * gl_raw_io(), gl_normal_io() and gl_update_size() without - * reentrancy issues. - * - * Input: - * term_handler void (*)(int) The signal handler to invoke when - * a process-terminating signal is - * received. - * susp_handler void (*)(int) The signal handler to invoke when - * a process-suspending signal is - * received. - * cont_handler void (*)(int) The signal handler to invoke when - * a process-resumption signal is - * received (ie. SIGCONT). - * size_handler void (*)(int) The signal handler to invoke when - * a terminal-resize signal (ie. SIGWINCH) - * is received. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int), - void (*cont_handler)(int), void (*size_handler)(int)) -{ - int i; -/* - * Search for signals of the specified classes, and assign the - * associated signal handler to them. - */ - for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { - const struct GlDefSignal *sig = gl_signal_list + i; - if(sig->attr & GLSA_SUSP) { - if(gl_set_tty_signal(sig->signo, susp_handler)) - return 1; - } else if(sig->attr & GLSA_TERM) { - if(gl_set_tty_signal(sig->signo, term_handler)) - return 1; - } else if(sig->attr & GLSA_CONT) { - if(gl_set_tty_signal(sig->signo, cont_handler)) - return 1; - } else if(sig->attr & GLSA_SIZE) { - if(gl_set_tty_signal(sig->signo, size_handler)) - return 1; - }; - }; - return 0; -} - -/*....................................................................... - * This is a private function of gl_tty_signals(). It installs a given - * signal handler, and arranges that when that signal handler is being - * invoked other signals are blocked. The latter is important to allow - * functions like gl_normal_io(), gl_raw_io() and gl_update_size() - * to be called from signal handlers. - * - * Input: - * signo int The signal to be trapped. - * handler void (*)(int) The signal handler to assign to the signal. - */ -static int gl_set_tty_signal(int signo, void (*handler)(int)) -{ - SigAction act; /* The signal handler configuation */ -/* - * Arrange to block all trappable signals except the one that is being - * assigned (the trapped signal will be blocked automatically by the - * system). - */ - gl_list_trappable_signals(&act.sa_mask); - sigdelset(&act.sa_mask, signo); -/* - * Assign the signal handler. - */ - act.sa_handler = handler; -/* - * There is only one portable signal handling flag, and it isn't - * relevant to us, so don't specify any flags. - */ - act.sa_flags = 0; -/* - * Register the signal handler. - */ - if(sigaction(signo, &act, NULL)) - return 1; - return 0; -} - -/*....................................................................... - * Display a left-justified string over multiple terminal lines, - * taking account of the current width of the terminal. Optional - * indentation and an optional prefix string can be specified to be - * displayed at the start of each new terminal line used. Similarly, - * an optional suffix can be specified to be displayed at the end of - * each terminal line. If needed, a single paragraph can be broken - * across multiple calls. Note that literal newlines in the input - * string can be used to force a newline at any point and that you - * should use this feature to explicitly end all paragraphs, including - * at the end of the last string that you write. Note that when a new - * line is started between two words that are separated by spaces, - * those spaces are not output, whereas when a new line is started - * because a newline character was found in the string, only the - * spaces before the newline character are discarded. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * indentation int The number of spaces of indentation to write - * at the beginning of each new terminal line. - * prefix const char * An optional prefix string to write after the - * indentation margin at the start of each new - * terminal line. You can specify NULL if no - * prefix is required. - * suffix const char * An optional suffix string to draw at the end - * of the terminal line. Spaces will be added - * where necessary to ensure that the suffix ends - * in the last column of the terminal line. If - * no suffix is desired, specify NULL. - * fill_char int The padding character to use when indenting - * the line or padding up to the suffix. - * def_width int If the terminal width isn't known, such as when - * writing to a pipe or redirecting to a file, - * this number specifies what width to assume. - * start int The number of characters already written to - * the start of the current terminal line. This - * is primarily used to allow individual - * paragraphs to be written over multiple calls - * to this function, but can also be used to - * allow you to start the first line of a - * paragraph with a different prefix or - * indentation than those specified above. - * string const char * The string to be written. - * Output: - * return int On error -1 is returned. Otherwise the - * return value is the terminal column index at - * which the cursor was left after writing the - * final word in the string. Successful return - * values can thus be passed verbatim to the - * 'start' arguments of subsequent calls to - * gl_display_text() to allow the printing of a - * paragraph to be broken across multiple calls - * to gl_display_text(). - */ -int gl_display_text(GetLine *gl, int indentation, const char *prefix, - const char *suffix, int fill_char, - int def_width, int start, const char *string) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_completion_action() */ -/* - * Check the arguments? - */ - if(!gl || !string) { - errno = EINVAL; - return -1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return -1; -/* - * Display the text while signals are blocked. - */ - status = _io_display_text(_io_write_stdio, gl->output_fp, indentation, - prefix, suffix, fill_char, - gl->ncolumn > 0 ? gl->ncolumn : def_width, - start, string); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * Block all of the signals that we are currently trapping. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * oldset sigset_t * The superseded process signal mask - * will be return in *oldset unless oldset is - * NULL. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_mask_signals(GetLine *gl, sigset_t *oldset) -{ -/* - * Block all signals in all_signal_set, along with any others that are - * already blocked by the application. - */ - if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) { - gl->signals_masked = 1; - return 0; - }; -/* - * On error attempt to query the current process signal mask, so - * that oldset be the correct process signal mask to restore later - * if the caller of this function ignores the error return value. - */ - if(oldset) - (void) sigprocmask(SIG_SETMASK, NULL, oldset); - gl->signals_masked = 0; - return 1; -} - -/*....................................................................... - * Restore a process signal mask that was previously returned via the - * oldset argument of gl_mask_signals(). - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * oldset sigset_t * The process signal mask to be restored. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_unmask_signals(GetLine *gl, sigset_t *oldset) -{ - gl->signals_masked = 0; - return sigprocmask(SIG_SETMASK, oldset, NULL) < 0; -} - -/*....................................................................... - * Arrange to temporarily catch the signals marked in gl->use_signal_set. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_catch_signals(GetLine *gl) -{ - return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0; -} - -/*....................................................................... - * Select the I/O mode to be used by gl_get_line(). - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * mode GlIOMode The I/O mode to establish. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_io_mode(GetLine *gl, GlIOMode mode) -{ - sigset_t oldset; /* The signals that were blocked on entry to this function */ - int status; /* The return status of _gl_io_mode() */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Check that the requested mode is known. - */ - switch(mode) { - case GL_NORMAL_MODE: - case GL_SERVER_MODE: - break; - default: - errno = EINVAL; - _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.", - END_ERR_MSG); - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Invoke the private body of this function. - */ - status = _gl_io_mode(gl, mode); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the public function, gl_io_mode(). - * It assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_io_mode(GetLine *gl, GlIOMode mode) -{ -/* - * Are we already in the specified mode? - */ - if(mode == gl->io_mode) - return 0; -/* - * First revert to normal I/O in the current I/O mode. - */ - _gl_normal_io(gl); -/* - * Record the new mode. - */ - gl->io_mode = mode; -/* - * Perform any actions needed by the new mode. - */ - if(mode==GL_SERVER_MODE) { - if(_gl_raw_io(gl, 1)) - return 1; - }; - return 0; -} - -/*....................................................................... - * Return extra information (ie. in addition to that provided by errno) - * about the last error to occur in either gl_get_line() or its - * associated public functions. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * buff char * An optional output buffer. Note that if the - * calling application calls any gl_*() - * functions from signal handlers, it should - * provide a buffer here, so that a copy of - * the latest error message can safely be made - * while signals are blocked. - * n size_t The allocated size of buff[]. - * Output: - * return const char * A pointer to the error message. This will - * be the buff argument, unless buff==NULL, in - * which case it will be a pointer to an - * internal error buffer. In the latter case, - * note that the contents of the returned buffer - * will change on subsequent calls to any gl_*() - * functions. - */ -const char *gl_error_message(GetLine *gl, char *buff, size_t n) -{ - if(!gl) { - static const char *msg = "NULL GetLine argument"; - if(buff) { - strncpy(buff, msg, n); - buff[n-1] = '\0'; - } else { - return msg; - }; - } else if(buff) { - sigset_t oldset; /* The signals that were blocked on entry to this block */ -/* - * Temporarily block all signals. - */ - gl_mask_signals(gl, &oldset); -/* - * Copy the error message into the specified buffer. - */ - if(buff && n > 0) { - strncpy(buff, _err_get_msg(gl->err), n); - buff[n-1] = '\0'; - }; -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - } else { - return _err_get_msg(gl->err); - }; - return buff; -} - -/*....................................................................... - * Return the signal mask used by gl_get_line(). This is the set of - * signals that gl_get_line() is currently configured to trap. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * set sigset_t * The set of signals will be returned in *set, - * in the form of a signal process mask, as - * used by sigaction(), sigprocmask(), - * sigpending(), sigsuspend(), sigsetjmp() and - * other standard POSIX signal-aware - * functions. - * Output: - * return int 0 - OK. - * 1 - Error (examine errno for reason). - */ -int gl_list_signals(GetLine *gl, sigset_t *set) -{ -/* - * Check the arguments. - */ - if(!gl || !set) { - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Copy the signal mask into *set. - */ - memcpy(set, &gl->all_signal_set, sizeof(*set)); - return 0; -} - -/*....................................................................... - * By default, gl_get_line() doesn't trap signals that are blocked - * when it is called. This default can be changed either on a - * per-signal basis by calling gl_trap_signal(), or on a global basis - * by calling this function. What this function does is add the - * GLS_UNBLOCK_SIG flag to all signals that are currently configured - * to be trapped by gl_get_line(), such that when subsequent calls to - * gl_get_line() wait for I/O, these signals are temporarily - * unblocked. This behavior is useful in non-blocking server-I/O mode, - * where it is used to avoid race conditions related to handling these - * signals externally to gl_get_line(). See the demonstration code in - * demo3.c, or the gl_handle_signal() man page for further - * information. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -void gl_catch_blocked(GetLine *gl) -{ - sigset_t oldset; /* The process signal mask to restore */ - GlSignalNode *sig; /* A signal node in gl->sigs */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return; - }; -/* - * Temporarily block all signals while we modify the contents of gl. - */ - gl_mask_signals(gl, &oldset); -/* - * Add the GLS_UNBLOCK_SIG flag to all configured signals. - */ - for(sig=gl->sigs; sig; sig=sig->next) - sig->flags |= GLS_UNBLOCK_SIG; -/* - * Restore the process signal mask that was superseded by the call - * to gl_mask_signals(). - */ - gl_unmask_signals(gl, &oldset); - return; -} - -/*....................................................................... - * Respond to signals who's default effects have important - * consequences to gl_get_line(). This is intended for use in - * non-blocking server mode, where the external event loop is - * responsible for catching signals. Signals that are handled include - * those that by default terminate or suspend the process, and the - * signal that indicates that the terminal size has changed. Note that - * this function is not signal safe and should thus not be called from - * a signal handler itself. See the gl_io_mode() man page for how it - * should be used. - * - * In the case of signals that by default terminate or suspend - * processes, command-line editing will be suspended, the terminal - * returned to a usable state, then the default disposition of the - * signal restored and the signal resent, in order to suspend or - * terminate the process. If the process subsequently resumes, - * command-line editing is resumed. - * - * In the case of signals that indicate that the terminal has been - * resized, the new size will be queried, and any input line that is - * being edited will be redrawn to fit the new dimensions of the - * terminal. - * - * Input: - * signo int The number of the signal to respond to. - * gl GetLine * The first element of an array of 'ngl' GetLine - * objects. - * ngl int The number of elements in the gl[] array. Normally - * this will be one. - */ -void gl_handle_signal(int signo, GetLine *gl, int ngl) -{ - int attr; /* The attributes of the specified signal */ - sigset_t all_signals; /* The set of trappable signals */ - sigset_t oldset; /* The process signal mask to restore */ - int i; -/* - * NULL operation? - */ - if(ngl < 1 || !gl) - return; -/* - * Look up the default attributes of the specified signal. - */ - attr = gl_classify_signal(signo); -/* - * If the signal isn't known, we are done. - */ - if(!attr) - return; -/* - * Temporarily block all signals while we modify the gl objects. - */ - gl_list_trappable_signals(&all_signals); - sigprocmask(SIG_BLOCK, &all_signals, &oldset); -/* - * Suspend or terminate the process? - */ - if(attr & (GLSA_SUSP | GLSA_TERM)) { - gl_suspend_process(signo, gl, ngl); -/* - * Resize the terminal? Note that ioctl() isn't defined as being - * signal safe, so we can't call gl_update_size() here. However, - * gl_get_line() checks for resizes on each call, so simply arrange - * for the application's event loop to call gl_get_line() as soon as - * it becomes possible to write to the terminal. Note that if the - * caller is calling select() or poll when this happens, these functions - * get interrupted, since a signal has been caught. - */ - } else if(attr & GLSA_SIZE) { - for(i=0; i<ngl; i++) - gl[i].pending_io = GLP_WRITE; - }; -/* - * Restore the process signal mask that was superseded by the call - * to gl_mask_signals(). - */ - sigprocmask(SIG_SETMASK, &oldset, NULL); - return; -} - -/*....................................................................... - * Respond to an externally caught process suspension or - * termination signal. - * - * After restoring the terminal to a usable state, suspend or - * terminate the calling process, using the original signal with its - * default disposition restored to do so. If the process subsequently - * resumes, resume editing any input lines that were being entered. - * - * Input: - * signo int The signal number to suspend the process with. Note - * that the default disposition of this signal will be - * restored before the signal is sent, so provided - * that the default disposition of this signal is to - * either suspend or terminate the application, - * that is what wil happen, regardless of what signal - * handler is currently assigned to this signal. - * gl GetLine * The first element of an array of 'ngl' GetLine objects - * whose terminals should be restored to a sane state - * while the application is suspended. - * ngl int The number of elements in the gl[] array. - */ -static void gl_suspend_process(int signo, GetLine *gl, int ngl) -{ - sigset_t only_signo; /* A signal set containing just signo */ - sigset_t oldset; /* The signal mask on entry to this function */ - sigset_t all_signals; /* A signal set containing all signals */ - struct sigaction old_action; /* The current signal handler */ - struct sigaction def_action; /* The default signal handler */ - int i; -/* - * Create a signal mask containing the signal that was trapped. - */ - sigemptyset(&only_signo); - sigaddset(&only_signo, signo); -/* - * Temporarily block all signals. - */ - gl_list_trappable_signals(&all_signals); - sigprocmask(SIG_BLOCK, &all_signals, &oldset); -/* - * Restore the terminal to a usable state. - */ - for(i=0; i<ngl; i++) { - GetLine *obj = gl + i; - if(obj->raw_mode) { - _gl_normal_io(obj); - if(!obj->raw_mode) /* Check that gl_normal_io() succeded */ - obj->raw_mode = -1; /* Flag raw mode as needing to be restored */ - }; - }; -/* - * Restore the system default disposition of the signal that we - * caught. Note that this signal is currently blocked. Note that we - * don't use memcpy() to copy signal sets here, because the signal safety - * of memcpy() is undefined. - */ - def_action.sa_handler = SIG_DFL; - { - char *orig = (char *) &all_signals; - char *dest = (char *) &def_action.sa_mask; - for(i=0; i<sizeof(sigset_t); i++) - *dest++ = *orig++; - }; - sigaction(signo, &def_action, &old_action); -/* - * Resend the signal, and unblock it so that it gets delivered to - * the application. This will invoke the default action of this signal. - */ - raise(signo); - sigprocmask(SIG_UNBLOCK, &only_signo, NULL); -/* - * If the process resumes again, it will resume here. - * Block the signal again, then restore our signal handler. - */ - sigprocmask(SIG_BLOCK, &only_signo, NULL); - sigaction(signo, &old_action, NULL); -/* - * Resume command-line editing. - */ - for(i=0; i<ngl; i++) { - GetLine *obj = gl + i; - if(obj->raw_mode == -1) { /* Did we flag the need to restore raw mode? */ - obj->raw_mode = 0; /* gl_raw_io() does nothing unless raw_mode==0 */ - _gl_raw_io(obj, 1); - }; - }; -/* - * Restore the process signal mask to the way it was when this function - * was called. - */ - sigprocmask(SIG_SETMASK, &oldset, NULL); - return; -} - -/*....................................................................... - * Return the information about the default attributes of a given signal. - * The attributes that are returned are as defined by the standards that - * created them, including POSIX, SVR4 and 4.3+BSD, and are taken from a - * table in Richard Steven's book, "Advanced programming in the UNIX - * environment". - * - * Input: - * signo int The signal to be characterized. - * Output: - * return int A bitwise union of GlSigAttr enumerators, or 0 - * if the signal isn't known. - */ -static int gl_classify_signal(int signo) -{ - int i; -/* - * Search for the specified signal in the gl_signal_list[] table. - */ - for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { - const struct GlDefSignal *sig = gl_signal_list + i; - if(sig->signo == signo) - return sig->attr; - }; -/* - * Signal not known. - */ - return 0; -} - -/*....................................................................... - * When in non-blocking server mode, this function can be used to abandon - * the current incompletely entered input line, and prepare to start - * editing a new line on the next call to gl_get_line(). - * - * Input: - * gl GetLine * The line editor resource object. - */ -void gl_abandon_line(GetLine *gl) -{ - sigset_t oldset; /* The process signal mask to restore */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return; - }; -/* - * Temporarily block all signals while we modify the contents of gl. - */ - gl_mask_signals(gl, &oldset); -/* - * Mark the input line as discarded. - */ - _gl_abandon_line(gl); -/* - * Restore the process signal mask that was superseded by the call - * to gl_mask_signals(). - */ - gl_unmask_signals(gl, &oldset); - return; -} - -/*....................................................................... - * This is the private body of the gl_abandon_line() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -void _gl_abandon_line(GetLine *gl) -{ - gl->endline = 1; - gl->pending_io = GLP_WRITE; -} - -/*....................................................................... - * How many characters are needed to write a number as an octal string? - * - * Input: - * num unsigned The to be measured. - * Output: - * return int The number of characters needed. - */ -static int gl_octal_width(unsigned num) -{ - int n; /* The number of characters needed to render the number */ - for(n=1; num /= 8; n++) - ; - return n; -} - -/*....................................................................... - * Tell gl_get_line() the current terminal size. Note that this is only - * necessary on systems where changes in terminal size aren't reported - * via SIGWINCH. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * ncolumn int The number of columns in the terminal. - * nline int The number of lines in the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_set_term_size(GetLine *gl, int ncolumn, int nline) -{ - sigset_t oldset; /* The signals that were blocked on entry */ - /* to this function */ - int status; /* The return status */ -/* - * Block all signals while accessing gl. - */ - gl_mask_signals(gl, &oldset); -/* - * Install the new terminal size. - */ - status = _gl_set_term_size(gl, ncolumn, nline); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the gl_set_term_size() function. It - * assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline) -{ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Reject non-sensical dimensions. - */ - if(ncolumn <= 0 || nline <= 0) { - _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Install the new dimensions in the terminal driver if possible, so - * that future calls to gl_query_size() get the new value. - */ -#ifdef TIOCSWINSZ - if(gl->is_term) { - struct winsize size; - size.ws_row = nline; - size.ws_col = ncolumn; - size.ws_xpixel = 0; - size.ws_ypixel = 0; - if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) { - _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG); - return 1; - }; - }; -#endif -/* - * If an input line is in the process of being edited, redisplay it to - * accomodate the new dimensions, and record the new dimensions in - * gl->nline and gl->ncolumn. - */ - return gl_handle_tty_resize(gl, ncolumn, nline); -} - -/*....................................................................... - * Record a character in the input line buffer at a given position. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * c char The character to be recorded. - * bufpos int The index in the buffer at which to record the - * character. - * Output: - * return int 0 - OK. - * 1 - Insufficient room. - */ -static int gl_buffer_char(GetLine *gl, char c, int bufpos) -{ -/* - * Guard against buffer overruns. - */ - if(bufpos >= gl->linelen) - return 1; -/* - * Record the new character. - */ - gl->line[bufpos] = c; -/* - * If the new character was placed beyond the end of the current input - * line, update gl->ntotal to reflect the increased number of characters - * that are in gl->line, and terminate the string. - */ - if(bufpos >= gl->ntotal) { - gl->ntotal = bufpos+1; - gl->line[gl->ntotal] = '\0'; - }; - return 0; -} - -/*....................................................................... - * Copy a given string into the input buffer, overwriting the current - * contents. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * s const char * The string to be recorded. - * n int The number of characters to be copied from the - * string. - * bufpos int The index in the buffer at which to place the - * the first character of the string. - * Output: - * return int 0 - OK. - * 1 - String truncated to fit. - */ -static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos) -{ - int nnew; /* The number of characters actually recorded */ - int i; -/* - * How many of the characters will fit within the buffer? - */ - nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos); -/* - * Record the first nnew characters of s[] in the buffer. - */ - for(i=0; i<nnew; i++) - gl_buffer_char(gl, s[i], bufpos + i); -/* - * Was the string truncated? - */ - return nnew < n; -} - -/*....................................................................... - * Make room in the input buffer for a string to be inserted. This - * involves moving the characters that follow a specified point, towards - * the end of the buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * start int The index of the first character to be moved. - * n int The width of the gap. - * Output: - * return int 0 - OK. - * 1 - Insufficient room. - */ -static int gl_make_gap_in_buffer(GetLine *gl, int start, int n) -{ -/* - * Ensure that the buffer has sufficient space. - */ - if(gl->ntotal + n > gl->linelen) - return 1; -/* - * Move everything including and beyond the character at 'start' - * towards the end of the string. - */ - memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1); -/* - * Update the recorded size of the line. - */ - gl->ntotal += n; - return 1; -} - -/*....................................................................... - * Remove a given number of characters from the input buffer. This - * involves moving the characters that follow the removed characters to - * where the removed sub-string started in the input buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * start int The first character to be removed. - * n int The number of characters to remove. - */ -static void gl_remove_from_buffer(GetLine *gl, int start, int n) -{ - memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1); -/* - * Update the recorded size of the line. - */ - gl->ntotal -= n; -} - -/*....................................................................... - * Truncate the string in the input line buffer after a given number of - * characters. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * n int The new length of the line. - * Output: - * return int 0 - OK. - * 1 - n > gl->linelen. - */ -static int gl_truncate_buffer(GetLine *gl, int n) -{ - if(n > gl->linelen) - return 1; - gl->line[n] = '\0'; - gl->ntotal = n; - return 0; -} - -/*....................................................................... - * When the contents of gl->line[] are changed without calling any of the - * gl_ buffer manipulation functions, this function must be called to - * compute the length of this string, and ancillary information. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -static void gl_update_buffer(GetLine *gl) -{ - int len; /* The length of the line */ -/* - * Measure the length of the input line. - */ - for(len=0; len <= gl->linelen && gl->line[len]; len++) - ; -/* - * Just in case the string wasn't correctly terminated, do so here. - */ - gl->line[len] = '\0'; -/* - * Record the number of characters that are now in gl->line[]. - */ - gl->ntotal = len; -/* - * Ensure that the cursor stays within the bounds of the modified - * input line. - */ - if(gl->buff_curpos > gl->ntotal) - gl->buff_curpos = gl->ntotal; -/* - * Arrange for the input line to be redrawn. - */ - gl_queue_redisplay(gl); - return; -} - -/*....................................................................... - * Erase the displayed input line, including its prompt, and leave the - * cursor where the erased line started. Note that to allow this - * function to be used when responding to a terminal resize, this - * function is designed to work even if the horizontal cursor position - * doesn't match the internally recorded position. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_erase_line(GetLine *gl) -{ -/* - * Is a line currently displayed? - */ - if(gl->displayed) { -/* - * Relative the the start of the input line, which terminal line of - * the current input line is the cursor currently on? - */ - int cursor_line = gl->term_curpos / gl->ncolumn; -/* - * Move the cursor to the start of the line. - */ - for( ; cursor_line > 0; cursor_line--) { - if(gl_print_control_sequence(gl, 1, gl->up)) - return 1; - }; - if(gl_print_control_sequence(gl, 1, gl->bol)) - return 1; -/* - * Clear from the start of the line to the end of the terminal. - */ - if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Mark the line as no longer displayed. - */ - gl_line_erased(gl); - }; - return 0; -} - -/*....................................................................... - * Arrange for the input line to be redisplayed by gl_flush_output(), - * as soon as the output queue becomes empty. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -static void gl_queue_redisplay(GetLine *gl) -{ - gl->redisplay = 1; - gl->pending_io = GLP_WRITE; -} - -/*....................................................................... - * Truncate the displayed input line starting from the current - * terminal cursor position, and leave the cursor at the end of the - * truncated line. The input-line buffer is not affected. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_truncate_display(GetLine *gl) -{ -/* - * Keep a record of the current terminal cursor position. - */ - int term_curpos = gl->term_curpos; -/* - * First clear from the cursor to the end of the current input line. - */ - if(gl_print_control_sequence(gl, 1, gl->clear_eol)) - return 1; -/* - * If there is more than one line displayed, go to the start of the - * next line and clear from there to the end of the display. Note that - * we can't use clear_eod to do the whole job of clearing from the - * current cursor position to the end of the terminal because - * clear_eod is only defined when used at the start of a terminal line - * (eg. with gnome terminals, clear_eod clears from the start of the - * current terminal line, rather than from the current cursor - * position). - */ - if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) { - if(gl_print_control_sequence(gl, 1, gl->down) || - gl_print_control_sequence(gl, 1, gl->bol) || - gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Where is the cursor now? - */ - gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1); -/* - * Restore the cursor position. - */ - gl_set_term_curpos(gl, term_curpos); - }; -/* - * Update the recorded position of the final character. - */ - gl->term_len = gl->term_curpos; - return 0; -} - -/*....................................................................... - * Return the set of all trappable signals. - * - * Input: - * signals sigset_t * The set of signals will be recorded in - * *signals. - */ -static void gl_list_trappable_signals(sigset_t *signals) -{ -/* - * Start with the set of all signals. - */ - sigfillset(signals); -/* - * Remove un-trappable signals from this set. - */ -#ifdef SIGKILL - sigdelset(signals, SIGKILL); -#endif -#ifdef SIGSTOP - sigdelset(signals, SIGSTOP); -#endif -} - -/*....................................................................... - * Read an input line from a non-interactive input stream. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK - * 1 - Error. - */ -static int gl_read_stream_line(GetLine *gl) -{ - char c = '\0'; /* The latest character read from fp */ -/* - * Record the fact that we are about to read input. - */ - gl->pending_io = GLP_READ; -/* - * If we are starting a new line, reset the line-editing parameters, - * and discard the previous input line. - */ - if(gl->endline) { - gl_reset_editor(gl); - gl_truncate_buffer(gl, 0); - }; -/* - * Read one character at a time. - */ - while(gl->ntotal < gl->linelen && c != '\n') { -/* - * Attempt to read one more character. - */ - switch(gl_read_input(gl, &c)) { - case GL_READ_OK: - break; - case GL_READ_EOF: /* Reached end-of-file? */ -/* - * If any characters were read before the end-of-file condition, - * interpolate a newline character, so that the caller sees a - * properly terminated line. Otherwise return an end-of-file - * condition. - */ - if(gl->ntotal > 0) { - c = '\n'; - } else { - gl_record_status(gl, GLR_EOF, 0); - return 1; - }; - break; - case GL_READ_BLOCKED: /* Input blocked? */ - gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); - return 1; - break; - case GL_READ_ERROR: /* I/O error? */ - return 1; - break; - }; -/* - * Append the character to the line buffer. - */ - if(gl_buffer_char(gl, c, gl->ntotal)) - return 1; - }; -/* - * Was the end of the input line reached before running out of buffer space? - */ - gl->endline = (c == '\n'); - return 0; -} - -/*....................................................................... - * Read a single character from a non-interactive input stream. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int The character, or EOF on error. - */ -static int gl_read_stream_char(GetLine *gl) -{ - char c = '\0'; /* The latest character read from fp */ - int retval = EOF; /* The return value of this function */ -/* - * Arrange to discard any incomplete input line. - */ - _gl_abandon_line(gl); -/* - * Record the fact that we are about to read input. - */ - gl->pending_io = GLP_READ; -/* - * Attempt to read one more character. - */ - switch(gl_read_input(gl, &c)) { - case GL_READ_OK: /* Success */ - retval = c; - break; - case GL_READ_BLOCKED: /* The read blocked */ - gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); - retval = EOF; /* Failure */ - break; - case GL_READ_EOF: /* End of file reached */ - gl_record_status(gl, GLR_EOF, 0); - retval = EOF; /* Failure */ - break; - case GL_READ_ERROR: - retval = EOF; /* Failure */ - break; - }; - return retval; -} - -/*....................................................................... - * Bind a key sequence to a given action. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * origin GlKeyOrigin The originator of the key binding. - * key const char * The key-sequence to be bound (or unbound). - * action const char * The name of the action to bind the key to, - * or either NULL or "" to unbind the - * key-sequence. - * Output: - * return int 0 - OK - * 1 - Error. - */ -int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq, - const char *action) -{ - KtBinder binder; /* The private internal equivalent of 'origin' */ -/* - * Check the arguments. - */ - if(!gl || !keyseq) { - errno = EINVAL; - if(gl) - _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); - return 1; - }; -/* - * An empty action string requests that the key-sequence be unbound. - * This is indicated to _kt_set_keybinding() by passing a NULL action - * string, so convert an empty string to a NULL action pointer. - */ - if(action && *action=='\0') - action = NULL; -/* - * Translate the public originator enumeration to the private equivalent. - */ - binder = origin==GL_USER_KEY ? KTB_USER : KTB_NORM; -/* - * Bind the action to a given key-sequence? - */ - if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) { - _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); - return 1; - }; - return 0; -} - -/*....................................................................... - * This is the public wrapper around the gl_clear_termina() function. - * It clears the terminal and leaves the cursor at the home position. - * In server I/O mode, the next call to gl_get_line() will also - * redisplay the current input line. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_erase_terminal(GetLine *gl) -{ - sigset_t oldset; /* The signals that were blocked on entry */ - /* to this function */ - int status; /* The return status */ -/* - * Block all signals while accessing gl. - */ - gl_mask_signals(gl, &oldset); -/* - * Clear the terminal. - */ - status = gl_clear_screen(gl, 1, NULL); -/* - * Attempt to flush the clear-screen control codes to the terminal. - * If this doesn't complete the job, the next call to gl_get_line() - * will. - */ - (void) gl_flush_output(gl); -/* - * Restore the process signal mask before returning. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This function must be called by any function that erases the input - * line. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -static void gl_line_erased(GetLine *gl) -{ - gl->displayed = 0; - gl->term_curpos = 0; - gl->term_len = 0; -} - -/*....................................................................... - * Append a specified line to the history list. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * line const char * The line to be added. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_append_history(GetLine *gl, const char *line) -{ - sigset_t oldset; /* The signals that were blocked on entry */ - /* to this function */ - int status; /* The return status */ -/* - * Check the arguments. - */ - if(!gl || !line) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - status = _gl_append_history(gl, line); -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return status; -} - -/*....................................................................... - * This is the private body of the public function, gl_append_history(). - * It assumes that the caller has checked its arguments and blocked the - * delivery of signals. - */ -static int _gl_append_history(GetLine *gl, const char *line) -{ - int status =_glh_add_history(gl->glh, line, 0); - if(status) - _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); - return status; -} - -/*....................................................................... - * Enable or disable the automatic addition of newly entered lines to the - * history list. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * enable int If true, subsequently entered lines will - * automatically be added to the history list - * before they are returned to the caller of - * gl_get_line(). If 0, the choice of how and - * when to archive lines in the history list, - * is left up to the calling application, which - * can do so via calls to gl_append_history(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_automatic_history(GetLine *gl, int enable) -{ - sigset_t oldset; /* The signals that were blocked on entry */ - /* to this function */ -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return 1; - }; -/* - * Block all signals. - */ - if(gl_mask_signals(gl, &oldset)) - return 1; -/* - * Execute the private body of the function while signals are blocked. - */ - gl->automatic_history = enable; -/* - * Restore the process signal mask. - */ - gl_unmask_signals(gl, &oldset); - return 0; -} - -/*....................................................................... - * This is a public function that reads a single uninterpretted - * character from the user, without displaying anything. - * - * Input: - * gl GetLine * A resource object previously returned by - * new_GetLine(). - * Output: - * return int The character that was read, or EOF if the read - * had to be aborted (in which case you can call - * gl_return_status() to find out why). - */ -int gl_read_char(GetLine *gl) -{ - int retval; /* The return value of _gl_read_char() */ -/* - * This function can be called from application callback functions, - * so check whether signals have already been masked, so that we don't - * do it again, and overwrite gl->old_signal_set. - */ - int was_masked = gl->signals_masked; -/* - * Check the arguments. - */ - if(!gl) { - errno = EINVAL; - return EOF; - }; -/* - * Temporarily block all of the signals that we have been asked to trap. - */ - if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set)) - return EOF; -/* - * Perform the character reading task. - */ - retval = _gl_read_char(gl); -/* - * Restore the process signal mask to how it was when this function was - * first called. - */ - if(!was_masked) - gl_unmask_signals(gl, &gl->old_signal_set); - return retval; -} - -/*....................................................................... - * This is the main body of the public function gl_read_char(). - */ -static int _gl_read_char(GetLine *gl) -{ - int retval = EOF; /* The return value */ - int waserr = 0; /* True if an error occurs */ - char c; /* The character read */ -/* - * This function can be called from application callback functions, - * so check whether signals have already been overriden, so that we don't - * overwrite the preserved signal handlers with gl_get_line()s. Also - * record whether we are currently in raw I/O mode or not, so that this - * can be left in the same state on leaving this function. - */ - int was_overriden = gl->signals_overriden; - int was_raw = gl->raw_mode; -/* - * Also keep a record of the direction of any I/O that gl_get_line() - * is awaiting, so that we can restore this status on return. - */ - GlPendingIO old_pending_io = gl->pending_io; -/* - * Assume that this call will successfully complete the input operation - * until proven otherwise. - */ - gl_clear_status(gl); -/* - * If this is the first call to this function or gl_get_line(), - * since new_GetLine(), complete any postponed configuration. - */ - if(!gl->configured) { - (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); - gl->configured = 1; - }; -/* - * 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. - */ - if(!was_overriden) - waserr = gl_override_signal_handlers(gl); -/* - * After recording the current terminal settings, switch the terminal - * into raw input mode, without redisplaying any partially entered input - * line. - */ - if(!was_raw) - waserr = waserr || _gl_raw_io(gl, 0); -/* - * Attempt to read the line. This will require more than one attempt if - * either a current temporary input file is opened by gl_get_input_line() - * or the end of a temporary input file is reached by gl_read_stream_line(). - */ - while(!waserr) { -/* - * Read a line from a non-interactive stream? - */ - if(gl->file_fp || !gl->is_term) { - retval = gl_read_stream_char(gl); - if(retval != EOF) { /* Success? */ - break; - } else if(gl->file_fp) { /* End of temporary input file? */ - gl_revert_input(gl); - gl_record_status(gl, GLR_NEWLINE, 0); - } else { /* An error? */ - waserr = 1; - break; - }; - }; -/* - * Read from the terminal? Note that the above if() block may have - * changed gl->file_fp, so it is necessary to retest it here, rather - * than using an else statement. - */ - if(!gl->file_fp && gl->is_term) { -/* - * Flush any pending output to the terminal before waiting - * for the user to type a character. - */ - if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) { - retval = EOF; -/* - * Read one character. Don't append it to the key buffer, since - * this would subseuqnely appear as bogus input to the line editor. - */ - } else if(gl_read_terminal(gl, 0, &c) == 0) { -/* - * Record the character for return. - */ - retval = c; -/* - * In this mode, count each character as being a new key-sequence. - */ - gl->keyseq_count++; -/* - * Delete the character that was read, from the key-press buffer. - */ - gl_discard_chars(gl, 1); - }; - if(retval==EOF) - waserr = 1; - else - break; - }; - }; -/* - * If an error occurred, but gl->rtn_status is still set to - * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise - * leave it at whatever specific value was assigned by the function - * that aborted input. This means that only functions that trap - * non-generic errors have to remember to update gl->rtn_status - * themselves. - */ - if(waserr && gl->rtn_status == GLR_NEWLINE) - gl_record_status(gl, GLR_ERROR, errno); -/* - * Restore terminal settings, if they were changed by this function. - */ - if(!was_raw && gl->io_mode != GL_SERVER_MODE) - _gl_normal_io(gl); -/* - * Restore the signal handlers, if they were overriden by this function. - */ - if(!was_overriden) - gl_restore_signal_handlers(gl); -/* - * If this function gets aborted early, the errno value associated - * with the event that caused this to happen is recorded in - * gl->rtn_errno. Since errno may have been overwritten by cleanup - * functions after this, restore its value to the value that it had - * when the error condition occured, so that the caller can examine it - * to find out what happened. - */ - errno = gl->rtn_errno; -/* - * Error conditions are signalled to the caller, by setting the returned - * character to EOF. - */ - if(gl->rtn_status != GLR_NEWLINE) - retval = EOF; -/* - * Restore the indication of what direction of I/O gl_get_line() - * was awaiting before this call. - */ - gl->pending_io = old_pending_io; -/* - * Return the acquired character. - */ - return retval; -} - -/*....................................................................... - * Reset the GetLine completion status. This function should be called - * at the start of gl_get_line(), gl_read_char() and gl_query_char() - * to discard the completion status and non-zero errno value of any - * preceding calls to these functions. - * - * Input: - * gl GetLine * The resource object of this module. - */ -static void gl_clear_status(GetLine *gl) -{ - gl_record_status(gl, GLR_NEWLINE, 0); -} - -/*....................................................................... - * When an error or other event causes gl_get_line() to return, this - * function should be called to record information about what - * happened, including the value of errno and the value that - * gl_return_status() should return. - * - * Input: - * gl GetLine * The resource object of this module. - * rtn_status GlReturnStatus The completion status. To clear a - * previous abnormal completion status, - * specify GLR_NEWLINE (this is what - * gl_clear_status() does). - * rtn_errno int The associated value of errno. - */ -static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status, - int rtn_errno) -{ -/* - * If rtn_status==GLR_NEWLINE, then this resets the completion status, so we - * should always heed this. Otherwise, only record the first abnormal - * condition that occurs after such a reset. - */ - if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) { - gl->rtn_status = rtn_status; - gl->rtn_errno = rtn_errno; - }; -} - diff --git a/libtecla-1.6.1/getline.h b/libtecla-1.6.1/getline.h deleted file mode 100644 index 60a9c33..0000000 --- a/libtecla-1.6.1/getline.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef getline_h -#define getline_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/hash.c b/libtecla-1.6.1/hash.c deleted file mode 100644 index acaaff6..0000000 --- a/libtecla-1.6.1/hash.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.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; - -/* - * A hash-table consists of 'size' hash buckets. - * Note that the HashTable typedef for this struct is contained in hash.h. - */ -struct HashTable { - 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) { - errno = ENOMEM; - 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(sizeof(HashTable), hash_count); - if(!mem->hash_memory) - return _del_HashMemory(mem, 1); - mem->node_memory = _new_FreeList(sizeof(HashNode), node_count); - if(!mem->node_memory) - return _del_HashMemory(mem, 1); - mem->string_memory = _new_StringMem(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) -{ - if(mem) { - if(!force && (_busy_FreeListNodes(mem->hash_memory) > 0 || - _busy_FreeListNodes(mem->node_memory) > 0)) { - errno = EBUSY; - return NULL; - }; - mem->hash_memory = _del_FreeList(mem->hash_memory, force); - mem->node_memory = _del_FreeList(mem->node_memory, force); - mem->string_memory = _del_StringMem(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) { - errno = EINVAL; - 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) { - errno = ENOMEM; - 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->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) { - errno = ENOMEM; - 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) { - errno = EINVAL; - 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.6.1/hash.h b/libtecla-1.6.1/hash.h deleted file mode 100644 index 6cee6a2..0000000 --- a/libtecla-1.6.1/hash.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef hash_h -#define hash_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/history.c b/libtecla-1.6.1/history.c deleted file mode 100644 index cffa33e..0000000 --- a/libtecla-1.6.1/history.c +++ /dev/null @@ -1,2842 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 "ioutil.h" -#include "history.h" -#include "freelist.h" -#include "errmsg.h" - -/* - * History lines are split into sub-strings of GLH_SEG_SIZE - * characters. To avoid wasting space in the GlhLineSeg structure, - * this should be a multiple of the size of a pointer. - */ -#define GLH_SEG_SIZE 16 - -/* - * GlhLineSeg structures contain fixed sized segments of a larger - * string. These are linked into lists to record strings, with all but - * the last segment having GLH_SEG_SIZE characters. The last segment - * of a string is terminated within the GLH_SEG_SIZE characters with a - * '\0'. - */ -typedef struct GlhLineSeg GlhLineSeg; -struct GlhLineSeg { - GlhLineSeg *next; /* The next sub-string of the history line */ - char s[GLH_SEG_SIZE]; /* The sub-string. Beware that only the final */ - /* substring of a line, as indicated by 'next' */ - /* being NULL, is '\0' terminated. */ -}; - -/* - * History lines are recorded in a hash table, such that repeated - * lines are stored just once. - * - * Start by defining the size of the hash table. This should be a - * prime number. - */ -#define GLH_HASH_SIZE 113 - -typedef struct GlhHashBucket GlhHashBucket; - -/* - * Each history line will be represented in the hash table by a - * structure of the following type. - */ -typedef struct GlhHashNode GlhHashNode; -struct GlhHashNode { - GlhHashBucket *bucket; /* The parent hash-table bucket of this node */ - GlhHashNode *next; /* The next in the list of nodes within the */ - /* parent hash-table bucket. */ - GlhLineSeg *head; /* The list of sub-strings which make up a line */ - int len; /* The length of the line, excluding any '\0' */ - int used; /* The number of times this string is pointed to by */ - /* the time-ordered list of history lines. */ - int reported; /* A flag that is used when searching to ensure that */ - /* a line isn't reported redundantly. */ -}; - -/* - * How many new GlhHashNode elements should be allocated at a time? - */ -#define GLH_HASH_INCR 50 - -static int _glh_is_line(GlhHashNode *hash, const char *line, size_t n); -static int _glh_line_matches_prefix(GlhHashNode *line, GlhHashNode *prefix); -static void _glh_return_line(GlhHashNode *hash, char *line, size_t dim); - -/* - * All history lines which hash to a given bucket in the hash table, are - * recorded in a structure of the following type. - */ -struct GlhHashBucket { - GlhHashNode *lines; /* The list of history lines which fall in this bucket */ -}; - -static GlhHashBucket *glh_find_bucket(GlHistory *glh, const char *line, - size_t n); -static GlhHashNode *glh_find_hash_node(GlhHashBucket *bucket, const char *line, - size_t n); - -typedef struct { - FreeList *node_mem; /* A free-list of GlhHashNode structures */ - GlhHashBucket bucket[GLH_HASH_SIZE]; /* The buckets of the hash table */ -} GlhLineHash; - -/* - * GlhLineNode's are used to record history lines in time order. - */ -typedef struct GlhLineNode GlhLineNode; -struct GlhLineNode { - 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. */ - GlhLineNode *next; /* The next youngest line in the list */ - GlhLineNode *prev; /* The next oldest line in the list */ - GlhHashNode *line; /* The hash-table entry of the history line */ -}; - -/* - * The number of GlhLineNode elements per freelist block. - */ -#define GLH_LINE_INCR 100 - -/* - * Encapsulate the time-ordered list of historical lines. - */ -typedef struct { - FreeList *node_mem; /* A freelist of GlhLineNode objects */ - GlhLineNode *head; /* The oldest line in the list */ - GlhLineNode *tail; /* The newest line in the list */ -} GlhLineList; - -/* - * The _glh_lookup_history() returns copies of history lines in a - * dynamically allocated array. This array is initially allocated - * GLH_LOOKUP_SIZE bytes. If subsequently this size turns out to be - * too small, realloc() is used to increase its size to the required - * size plus GLH_LOOKUP_MARGIN. The idea of the later parameter is to - * reduce the number of realloc() operations needed. - */ -#define GLH_LBUF_SIZE 300 -#define GLH_LBUF_MARGIN 100 - -/* - * Encapsulate all of the resources needed to store historical input lines. - */ -struct GlHistory { - ErrMsg *err; /* The error-reporting buffer */ - GlhLineSeg *buffer; /* An array of sub-line nodes to be partitioned */ - /* into lists of sub-strings recording input lines. */ - int nbuff; /* The allocated dimension of buffer[] */ - GlhLineSeg *unused; /* The list of free nodes in buffer[] */ - GlhLineList list; /* A time ordered list of history lines */ - GlhLineNode *recall; /* The last line recalled, or NULL if no recall */ - /* session is currently active. */ - GlhLineNode *id_node;/* The node at which the last ID search terminated */ - GlhLineHash hash; /* A hash-table of reference-counted history lines */ - GlhHashNode *prefix; /* A pointer to a line containing the prefix that */ - /* is being searched for. Note that if prefix==NULL */ - /* and prefix_len>0, this means that no line in */ - /* the buffer starts with the requested prefix. */ - int prefix_len; /* The length of the prefix being searched for. */ - char *lbuf; /* The array in which _glh_lookup_history() returns */ - /* history lines */ - int lbuf_dim; /* The allocated size of lbuf[] */ - int nbusy; /* The number of line segments in buffer[] that are */ - /* currently being used to record sub-lines */ - int nfree; /* The number of line segments in buffer that are */ - /* not currently being used to record sub-lines */ - 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 */ -}; - -#ifndef WITHOUT_FILE_SYSTEM -static int _glh_cant_load_history(GlHistory *glh, const char *filename, - int lineno, const char *message, FILE *fp); -static int _glh_cant_save_history(GlHistory *glh, const char *message, - const char *filename, FILE *fp); -static int _glh_write_timestamp(FILE *fp, time_t timestamp); -static int _glh_decode_timestamp(char *string, char **endp, time_t *timestamp); -#endif -static void _glh_discard_line(GlHistory *glh, GlhLineNode *node); -static GlhLineNode *_glh_find_id(GlHistory *glh, GlhLineID id); -static GlhHashNode *_glh_acquire_copy(GlHistory *glh, const char *line, - size_t n); -static GlhHashNode *_glh_discard_copy(GlHistory *glh, GlhHashNode *hnode); -static int _glh_prepare_for_recall(GlHistory *glh, char *line); - -/* - * The following structure and functions are used to iterate through - * the characters of a segmented history line. - */ -typedef struct { - GlhLineSeg *seg; /* The line segment that the next character will */ - /* be returned from. */ - int posn; /* The index in the above line segment, containing */ - /* the next unread character. */ - char c; /* The current character in the input line */ -} GlhLineStream; -static void glh_init_stream(GlhLineStream *str, GlhHashNode *line); -static void glh_step_stream(GlhLineStream *str); - -/* - * See if search prefix contains any globbing characters. - */ -static int glh_contains_glob(GlhHashNode *prefix); -/* - * Match a line against a search pattern. - */ -static int glh_line_matches_glob(GlhLineStream *lstr, GlhLineStream *pstr); -static int glh_matches_range(char c, GlhLineStream *pstr); - -/*....................................................................... - * Create a line history maintenance object. - * - * Input: - * buflen size_t The number of bytes to allocate to the - * 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 */ - int i; -/* - * Allocate the container. - */ - glh = (GlHistory *) malloc(sizeof(GlHistory)); - if(!glh) { - errno = ENOMEM; - 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->err = NULL; - glh->buffer = NULL; - glh->nbuff = (buflen+GLH_SEG_SIZE-1) / GLH_SEG_SIZE; - glh->unused = NULL; - glh->list.node_mem = NULL; - glh->list.head = glh->list.tail = NULL; - glh->recall = NULL; - glh->id_node = NULL; - glh->hash.node_mem = NULL; - for(i=0; i<GLH_HASH_SIZE; i++) - glh->hash.bucket[i].lines = NULL; - glh->prefix = NULL; - glh->lbuf = NULL; - glh->lbuf_dim = 0; - glh->nbusy = 0; - glh->nfree = glh->nbuff; - glh->seq = 0; - glh->group = 0; - glh->nline = 0; - glh->max_lines = -1; - glh->enable = 1; -/* - * Allocate a place to record error messages. - */ - glh->err = _new_ErrMsg(); - if(!glh->err) - return _del_GlHistory(glh); -/* - * Allocate the buffer, if required. - */ - if(glh->nbuff > 0) { - glh->nbuff = glh->nfree; - glh->buffer = (GlhLineSeg *) malloc(sizeof(GlhLineSeg) * glh->nbuff); - if(!glh->buffer) { - errno = ENOMEM; - return _del_GlHistory(glh); - }; -/* - * All nodes of the buffer are currently unused, so link them all into - * a list and make glh->unused point to the head of this list. - */ - glh->unused = glh->buffer; - for(i=0; i<glh->nbuff-1; i++) { - GlhLineSeg *seg = glh->unused + i; - seg->next = seg + 1; - }; - glh->unused[i].next = NULL; - }; -/* - * Allocate the GlhLineNode freelist. - */ - glh->list.node_mem = _new_FreeList(sizeof(GlhLineNode), GLH_LINE_INCR); - if(!glh->list.node_mem) - return _del_GlHistory(glh); -/* - * Allocate the GlhHashNode freelist. - */ - glh->hash.node_mem = _new_FreeList(sizeof(GlhLineNode), GLH_HASH_INCR); - if(!glh->hash.node_mem) - return _del_GlHistory(glh); -/* - * Allocate the array that _glh_lookup_history() uses to return a - * copy of a given history line. This will be resized when necessary. - */ - glh->lbuf_dim = GLH_LBUF_SIZE; - glh->lbuf = (char *) malloc(glh->lbuf_dim); - if(!glh->lbuf) { - errno = ENOMEM; - 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 error-message buffer. - */ - glh->err = _del_ErrMsg(glh->err); -/* - * Delete the buffer. - */ - if(glh->buffer) { - free(glh->buffer); - glh->buffer = NULL; - glh->unused = NULL; - }; -/* - * Delete the freelist of GlhLineNode's. - */ - glh->list.node_mem = _del_FreeList(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 freelist of GlhHashNode's. - */ - glh->hash.node_mem = _del_FreeList(glh->hash.node_mem, 1); -/* - * Delete the lookup buffer. - */ - if(glh->lbuf) - free(glh->lbuf); -/* - * Delete the container. - */ - free(glh); - }; - return NULL; -} - -/*....................................................................... - * Append a new line to the history list, deleting old lines to make - * room, 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 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) -{ - int slen; /* The length of the line to be recorded (minus the '\0') */ - int empty; /* True if the string is empty */ - const char *nlptr; /* A pointer to a newline character in line[] */ - GlhHashNode *hnode; /* The hash-table node of the line */ - GlhLineNode *lnode; /* A node in the time-ordered list of lines */ - int i; -/* - * Check the arguments. - */ - if(!glh || !line) { - errno = EINVAL; - return 1; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return 0; -/* - * Cancel any ongoing search. - */ - if(_glh_cancel_search(glh)) - return 1; -/* - * How long is the string to be recorded, being careful not to include - * any terminating '\n' character. - */ - nlptr = strchr(line, '\n'); - if(nlptr) - slen = (nlptr - line); - else - slen = strlen(line); -/* - * Is the line empty? - */ - empty = 1; - for(i=0; i<slen && 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; -/* - * Has an upper limit to the number of lines in the history list been - * specified? - */ - if(glh->max_lines >= 0) { -/* - * If necessary, remove old lines until there is room to add one new - * line without exceeding the specified line limit. - */ - while(glh->nline > 0 && glh->nline >= glh->max_lines) - _glh_discard_line(glh, glh->list.head); -/* - * We can't archive the line if the maximum number of lines allowed is - * zero. - */ - if(glh->max_lines == 0) - return 0; - }; -/* - * Unless already stored, store a copy of the line in the history buffer, - * then return a reference-counted hash-node pointer to this copy. - */ - hnode = _glh_acquire_copy(glh, line, slen); - if(!hnode) { - _err_record_msg(glh->err, "No room to store history line", END_ERR_MSG); - errno = ENOMEM; - return 1; - }; -/* - * Allocate a new node in the time-ordered list of lines. - */ - lnode = (GlhLineNode *) _new_FreeListNode(glh->list.node_mem); -/* - * If a new line-node couldn't be allocated, discard our copy of the - * stored line before reporting the error. - */ - if(!lnode) { - hnode = _glh_discard_copy(glh, hnode); - _err_record_msg(glh->err, "No room to store history line", END_ERR_MSG); - errno = ENOMEM; - return 1; - }; -/* - * Record a pointer to the hash-table record of the line in the new - * list node. - */ - lnode->id = glh->seq++; - lnode->timestamp = time(NULL); - lnode->group = glh->group; - lnode->line = hnode; -/* - * Append the new node to the end of the time-ordered list. - */ - if(glh->list.head) - glh->list.tail->next = lnode; - else - glh->list.head = lnode; - lnode->next = NULL; - lnode->prev = glh->list.tail; - glh->list.tail = lnode; -/* - * Record the addition of a line to the list. - */ - 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 dimension 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) -{ - GlhLineNode *node; /* The line location node being checked */ - GlhHashNode *old_line; /* The previous recalled line */ -/* - * Check the arguments. - */ - if(!glh || !line) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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) { - _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)", - END_ERR_MSG); - errno = EINVAL; - return NULL; - }; -/* - * Preserve the input line if needed. - */ - if(_glh_prepare_for_recall(glh, line)) - return NULL; -/* - * From where should we start the search? - */ - if(glh->recall) { - node = glh->recall->prev; - old_line = glh->recall->line; - } else { - node = glh->list.tail; - old_line = NULL; - }; -/* - * Search backwards through the list for the first match with the - * prefix string that differs from the last line that was recalled. - */ - while(node && (node->group != glh->group || node->line == old_line || - !_glh_line_matches_prefix(node->line, glh->prefix))) - 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. - */ - _glh_return_line(node->line, line, dim); -/* - * Return it. - */ - 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) -{ - GlhLineNode *node; /* The line location node being checked */ - GlhHashNode *old_line; /* The previous recalled line */ -/* - * Check the arguments. - */ - if(!glh || !line) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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) { - _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)", - END_ERR_MSG); - errno = EINVAL; - return NULL; - }; -/* - * From where should we start the search? - */ - if(glh->recall) { - node = glh->recall->next; - old_line = glh->recall->line; - } else { - return NULL; - }; -/* - * Search forwards through the list for the first match with the - * prefix string. - */ - while(node && (node->group != glh->group || node->line == old_line || - !_glh_line_matches_prefix(node->line, glh->prefix))) - node = node->next; -/* - * Was a matching line found? - */ - if(node) { -/* - * Copy the matching line into the provided line buffer. - */ - _glh_return_line(node->line, line, dim); -/* - * Record the starting point of the next search. - */ - glh->recall = node; -/* - * If we just returned the line that was being entered when the search - * session first started, cancel the search. - */ - if(node == glh->list.tail) - _glh_cancel_search(glh); -/* - * 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) { - errno = EINVAL; - return 1; - }; -/* - * If there wasn't a search in progress, do nothing. - */ - if(!glh->recall) - return 0; -/* - * Reset the search pointers. Note that it is essential to set - * glh->recall to NULL before calling _glh_discard_line(), to avoid an - * infinite recursion. - */ - glh->recall = NULL; -/* - * Delete the node of the preserved line. - */ - _glh_discard_line(glh, glh->list.tail); - return 0; -} - -/*....................................................................... - * Set the prefix of subsequent history searches. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line const 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) -{ -/* - * Check the arguments. - */ - if(!glh) { - errno = EINVAL; - return 1; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return 0; -/* - * Discard any existing prefix. - */ - glh->prefix = _glh_discard_copy(glh, glh->prefix); -/* - * Only store a copy of the prefix string if it isn't a zero-length string. - */ - if(prefix_len > 0) { -/* - * Get a reference-counted copy of the prefix from the history cache buffer. - */ - glh->prefix = _glh_acquire_copy(glh, line, prefix_len); -/* - * Was there insufficient buffer space? - */ - if(!glh->prefix) { - _err_record_msg(glh->err, "The search prefix is too long to store", - END_ERR_MSG); - errno = ENOMEM; - return 1; - }; - }; - 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) -{ - GlhLineNode *node; /* The line location node being checked */ -/* - * Check the arguments. - */ - if(!glh || !line) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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) { - _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)", - END_ERR_MSG); - errno = EINVAL; - return NULL; - }; -/* - * Preserve the input line if needed. - */ - if(_glh_prepare_for_recall(glh, line)) - return NULL; -/* - * 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. - */ - _glh_return_line(node->line, line, dim); -/* - * If we just returned the line that was being entered when the search - * session first started, cancel the search. - */ - if(node == glh->list.tail) - _glh_cancel_search(glh); - 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) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return NULL; - }; -/* - * If history isn't enabled, or no history search has yet been started, - * ignore the call. - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0 || !glh->recall) - return NULL; -/* - * Check the line dimensions. - */ - if(dim < strlen(line) + 1) { - _err_record_msg(glh->err, "'dim' argument inconsistent with strlen(line)", - END_ERR_MSG); - errno = EINVAL; - return NULL; - }; -/* - * Copy the recalled line into the provided line buffer. - */ - _glh_return_line(glh->list.tail->line, line, dim); -/* - * Since we have returned to the starting point of the search, cancel it. - */ - _glh_cancel_search(glh); - 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) -{ - GlhLineNode *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) -{ - GlhLineNode *node; /* The line location node being checked */ -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return NULL; -/* - * Preserve the input line if needed. - */ - if(_glh_prepare_for_recall(glh, line)) - 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. - */ - _glh_return_line(node->line, line, dim); - 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) -{ -#ifdef WITHOUT_FILE_SYSTEM - _err_record_msg(glh->err, "Can't save history without filesystem access", - END_ERR_MSG); - errno = EINVAL; - return 1; -#else - FILE *fp; /* The output file */ - GlhLineNode *node; /* The line being saved */ - GlhLineNode *head; /* The head of the list of lines to be saved */ - GlhLineSeg *seg; /* One segment of a line being saved */ -/* - * Check the arguments. - */ - if(!glh || !filename || !comment) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - return 1; - }; -/* - * Attempt to open the specified file. - */ - fp = fopen(filename, "w"); - if(!fp) - return _glh_cant_save_history(glh, "Can't open", filename, NULL); -/* - * 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) { - return _glh_cant_save_history(glh, "Error writing", filename, fp); - }; -/* - * Write the history line. - */ - for(seg=node->line->head; seg; seg=seg->next) { - size_t slen = seg->next ? GLH_SEG_SIZE : strlen(seg->s); - if(fwrite(seg->s, sizeof(char), slen, fp) != slen) - return _glh_cant_save_history(glh, "Error writing", filename, fp); - }; - fputc('\n', fp); - }; -/* - * Close the history file. - */ - if(fclose(fp) == EOF) - return _glh_cant_save_history(glh, "Error writing", filename, NULL); - return 0; -#endif -} - -#ifndef WITHOUT_FILE_SYSTEM -/*....................................................................... - * This is a private error return function of _glh_save_history(). It - * composes an error report in the error buffer, composed using - * sprintf("%s %s (%s)", message, filename, strerror(errno)). It then - * closes fp and returns the error return code of _glh_save_history(). - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * message const char * A message to be followed by the filename. - * filename const char * The name of the offending output file. - * fp FILE * The stream to be closed (send NULL if not - * open). - * Output: - * return int Always 1. - */ -static int _glh_cant_save_history(GlHistory *glh, const char *message, - const char *filename, FILE *fp) -{ - _err_record_msg(glh->err, message, filename, " (", - strerror(errno), ")", END_ERR_MSG); - if(fp) - (void) fclose(fp); - return 1; -} - -/*....................................................................... - * 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; -} - -#endif - -/*....................................................................... - * 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) -{ -#ifdef WITHOUT_FILE_SYSTEM - _err_record_msg(glh->err, "Can't load history without filesystem access", - END_ERR_MSG); - errno = EINVAL; - return 1; -#else - 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) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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; -#endif -} - -#ifndef WITHOUT_FILE_SYSTEM -/*....................................................................... - * 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) -{ - char lnum[20]; -/* - * Convert the line number to a string. - */ - sprintf(lnum, "%d", lineno); -/* - * Render an error message. - */ - _err_record_msg(glh->err, filename, ":", lnum, ":", message, END_ERR_MSG); -/* - * Close the file. - */ - if(fp) - (void) fclose(fp); - return 1; -} - -/*....................................................................... - * 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; -} -#endif - -/*....................................................................... - * 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) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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; -} - -/*....................................................................... - * Display the contents of the history list. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * write_fn GlWriteFn * The function to call to write the line, or - * 0 to discard the output. - * data void * Anonymous data to pass to write_fn(). - * 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, GlWriteFn *write_fn, void *data, - const char *fmt, int all_groups, int max_lines) -{ - GlhLineNode *node; /* The line being displayed */ - GlhLineNode *oldest; /* The oldest line to display */ - GlhLineSeg *seg; /* One segment of a line being displayed */ - 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 */ - int len; /* The length of a string to be written */ -/* - * Check the arguments. - */ - if(!glh || !write_fn || !fmt) { - if(glh) - _err_record_msg(glh->err, "NULL argument(s)", END_ERR_MSG); - errno = EINVAL; - 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) { - len = (int) (fptr - start); - if(write_fn(data, start, len) != len) - 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) { - len = strlen(buffer); - if(write_fn(data, buffer, len) != len) - return 1; - }; - break; - case 'T': /* Display the time of day */ - if(t && strftime(buffer, TSMAX, "%H:%M:%S", t) != 0) { - len = strlen(buffer); - if(write_fn(data, buffer, len) != len) - return 1; - }; - break; - case 'N': /* Display the sequential entry number */ - sprintf(buffer, "%*lu", idlen, (unsigned long) node->id); - len = strlen(buffer); - if(write_fn(data, buffer, len) != len) - return 1; - break; - case 'G': - sprintf(buffer, "%*u", grplen, (unsigned) node->group); - len = strlen(buffer); - if(write_fn(data, buffer, len) != len) - return 1; - break; - case 'H': /* Display the history line */ - for(seg=node->line->head; seg; seg=seg->next) { - len = seg->next ? GLH_SEG_SIZE : strlen(seg->s); - if(write_fn(data, seg->s, len) != len) - return 1; - }; - break; - case '%': /* A literal % symbol */ - if(write_fn(data, "%", 1) != 1) - 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) -{ - int nbuff; /* The number of segments in the new buffer */ - int i; -/* - * Check the arguments. - */ - if(!glh) { - errno = EINVAL; - return 1; - }; -/* - * How many buffer segments does the requested buffer size correspond - * to? - */ - nbuff = (bufsize+GLH_SEG_SIZE-1) / GLH_SEG_SIZE; -/* - * Has a different size than the current size been requested? - */ - if(glh->nbuff != nbuff) { -/* - * Cancel any ongoing search. - */ - (void) _glh_cancel_search(glh); -/* - * Create a wholly new buffer? - */ - if(glh->nbuff == 0 && nbuff>0) { - glh->buffer = (GlhLineSeg *) malloc(sizeof(GlhLineSeg) * nbuff); - if(!glh->buffer) - return 1; - glh->nbuff = nbuff; - glh->nfree = glh->nbuff; - glh->nbusy = 0; - glh->nline = 0; -/* - * Link the currently unused nodes of the buffer into a list. - */ - glh->unused = glh->buffer; - for(i=0; i<glh->nbuff-1; i++) { - GlhLineSeg *seg = glh->unused + i; - seg->next = seg + 1; - }; - glh->unused[i].next = NULL; -/* - * Delete an existing buffer? - */ - } else if(nbuff == 0) { - _glh_clear_history(glh, 1); - free(glh->buffer); - glh->buffer = NULL; - glh->unused = NULL; - glh->nbuff = 0; - glh->nfree = 0; - glh->nbusy = 0; - glh->nline = 0; -/* - * Change from one finite buffer size to another? - */ - } else { - GlhLineSeg *buffer; /* The resized buffer */ - int nbusy; /* The number of used line segments in the new buffer */ -/* - * Starting from the oldest line in the buffer, discard lines until - * the buffer contains at most 'nbuff' used line segments. - */ - while(glh->list.head && glh->nbusy > nbuff) - _glh_discard_line(glh, glh->list.head); -/* - * Attempt to allocate a new buffer. - */ - buffer = (GlhLineSeg *) malloc(nbuff * sizeof(GlhLineSeg)); - if(!buffer) { - errno = ENOMEM; - return 1; - }; -/* - * Copy the used segments of the old buffer to the start of the new buffer. - */ - nbusy = 0; - for(i=0; i<GLH_HASH_SIZE; i++) { - GlhHashBucket *b = glh->hash.bucket + i; - GlhHashNode *hnode; - for(hnode=b->lines; hnode; hnode=hnode->next) { - GlhLineSeg *seg = hnode->head; - hnode->head = buffer + nbusy; - for( ; seg; seg=seg->next) { - buffer[nbusy] = *seg; - buffer[nbusy].next = seg->next ? &buffer[nbusy+1] : NULL; - nbusy++; - }; - }; - }; -/* - * Make a list of the new buffer's unused segments. - */ - for(i=nbusy; i<nbuff-1; i++) - buffer[i].next = &buffer[i+1]; - if(i < nbuff) - buffer[i].next = NULL; -/* - * Discard the old buffer. - */ - free(glh->buffer); -/* - * Install the new buffer. - */ - glh->buffer = buffer; - glh->nbuff = nbuff; - glh->nbusy = nbusy; - glh->nfree = nbuff - nbusy; - glh->unused = glh->nfree > 0 ? (buffer + nbusy) : NULL; - }; - }; - 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; - GlhLineNode *node; - for(node=glh->list.tail; node && ++nline <= max_lines; node=node->prev) - ; -/* - * Discard any lines that exceed the limit. - */ - if(node) { - GlhLineNode *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_line(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) -{ - int i; -/* - * 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) { -/* - * Claer the time-ordered list of lines. - */ - _rst_FreeList(glh->list.node_mem); - glh->list.head = glh->list.tail = NULL; - glh->nline = 0; - glh->id_node = NULL; -/* - * Clear the hash table. - */ - for(i=0; i<GLH_HASH_SIZE; i++) - glh->hash.bucket[i].lines = NULL; - _rst_FreeList(glh->hash.node_mem); -/* - * Move all line segment nodes back onto the list of unused segments. - */ - if(glh->buffer) { - glh->unused = glh->buffer; - for(i=0; i<glh->nbuff-1; i++) { - GlhLineSeg *seg = glh->unused + i; - seg->next = seg + 1; - }; - glh->unused[i].next = NULL; - glh->nfree = glh->nbuff; - glh->nbusy = 0; - } else { - glh->unused = NULL; - glh->nbusy = glh->nfree = 0; - }; -/* - * Just delete lines of the current group? - */ - } else { - GlhLineNode *node; /* The line node being checked */ - GlhLineNode *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_line(glh, node); - }; - }; - 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; -} - -/*....................................................................... - * Discard a given archived input line. - * - * Input: - * glh GlHistory * The history container object. - * node GlhLineNode * The line to be discarded, specified via its - * entry in the time-ordered list of historical - * input lines. - */ -static void _glh_discard_line(GlHistory *glh, GlhLineNode *node) -{ -/* - * Remove the node from the linked list. - */ - if(node->prev) - node->prev->next = node->next; - else - glh->list.head = node->next; - 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; -/* - * If we are deleting the node that is marked as the start point of the - * next prefix search, cancel the search. - */ - if(node == glh->recall) - _glh_cancel_search(glh); -/* - * Delete our copy of the line. - */ - node->line = _glh_discard_copy(glh, node->line); -/* - * Return the node to the freelist. - */ - (void) _del_FreeListNode(glh->list.node_mem, node); -/* - * Record the removal of a line from the list. - */ - glh->nline--; - return; -} - -/*....................................................................... - * 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 a copy of the history line will be - * assigned to *line. Beware that this pointer may - * be invalidated by the next call to any public - * history function. - * 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) -{ - GlhLineNode *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, id); -/* - * Not found? - */ - if(!node) - return 0; -/* - * Has the history line been requested? - */ - if(line) { -/* - * If necessary, reallocate the lookup buffer to accomodate the size of - * a copy of the located line. - */ - if(node->line->len + 1 > glh->lbuf_dim) { - int lbuf_dim = node->line->len + 1; - char *lbuf = realloc(glh->lbuf, lbuf_dim); - if(!lbuf) { - errno = ENOMEM; - return 0; - }; - glh->lbuf_dim = lbuf_dim; - glh->lbuf = lbuf; - }; -/* - * Copy the history line into the lookup buffer. - */ - _glh_return_line(node->line, glh->lbuf, glh->lbuf_dim); -/* - * Assign the lookup buffer as the returned line pointer. - */ - *line = glh->lbuf; - }; -/* - * Does the caller want to know the group of the line? - */ - if(group) - *group = node->group; -/* - * Does the caller want to know the timestamp of the line? - */ - 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 GlhLIneNode * The located node, or NULL if not found. - */ -static GlhLineNode *_glh_find_id(GlHistory *glh, GlhLineID id) -{ - GlhLineNode *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->nbusy + glh->nfree) * GLH_SEG_SIZE; -/* - * Determine the amount of buffer space that is currently occupied. - */ - if(buff_used) - *buff_used = glh->nbusy * GLH_SEG_SIZE; - }; -} - -/*....................................................................... - * Return extra information (ie. in addition to that provided by errno) - * about the last error to occur in any of the public functions of this - * module. - * - * Input: - * glh GlHistory * The container of the history list. - * Output: - * return const char * A pointer to the internal buffer in which - * the error message is temporarily stored. - */ -const char *_glh_last_error(GlHistory *glh) -{ - return glh ? _err_get_msg(glh->err) : "NULL GlHistory argument"; -} - -/*....................................................................... - * Unless already stored, store a copy of the line in the history buffer, - * then return a reference-counted hash-node pointer to this copy. - * - * Input: - * glh GlHistory * The history maintenance buffer. - * line const char * The history line to be recorded. - * n size_t The length of the string, excluding any '\0' - * terminator. - * Output: - * return GlhHashNode * The hash-node containing the stored line, or - * NULL on error. - */ -static GlhHashNode *_glh_acquire_copy(GlHistory *glh, const char *line, - size_t n) -{ - GlhHashBucket *bucket; /* The hash-table bucket of the line */ - GlhHashNode *hnode; /* The hash-table node of the line */ - int i; -/* - * In which bucket should the line be recorded? - */ - bucket = glh_find_bucket(glh, line, n); -/* - * Is the line already recorded there? - */ - hnode = glh_find_hash_node(bucket, line, n); -/* - * If the line isn't recorded in the buffer yet, make room for it. - */ - if(!hnode) { - GlhLineSeg *seg; /* A line segment */ - int offset; /* An offset into line[] */ -/* - * How many string segments will be needed to record the new line, - * including space for a '\0' terminator? - */ - int nseg = ((n+1) + GLH_SEG_SIZE-1) / GLH_SEG_SIZE; -/* - * Discard the oldest history lines in the buffer until at least - * 'nseg' segments have been freed up, or until we run out of buffer - * space. - */ - while(glh->nfree < nseg && glh->nbusy > 0) - _glh_discard_line(glh, glh->list.head); -/* - * If the buffer is smaller than the new line, don't attempt to truncate - * it to fit. Simply don't archive it. - */ - if(glh->nfree < nseg) - return NULL; -/* - * Record the line in the first 'nseg' segments of the list of unused segments. - */ - offset = 0; - for(i=0,seg=glh->unused; i<nseg-1; i++,seg=seg->next, offset+=GLH_SEG_SIZE) - memcpy(seg->s, line + offset, GLH_SEG_SIZE); - memcpy(seg->s, line + offset, n-offset); - seg->s[n-offset] = '\0'; -/* - * Create a new hash-node for the line. - */ - hnode = (GlhHashNode *) _new_FreeListNode(glh->hash.node_mem); - if(!hnode) - return NULL; -/* - * Move the copy of the line from the list of unused segments to - * the hash node. - */ - hnode->head = glh->unused; - glh->unused = seg->next; - seg->next = NULL; - glh->nbusy += nseg; - glh->nfree -= nseg; -/* - * Prepend the new hash node to the list within the associated bucket. - */ - hnode->next = bucket->lines; - bucket->lines = hnode; -/* - * Initialize the rest of the members of the hash node. - */ - hnode->len = n; - hnode->reported = 0; - hnode->used = 0; - hnode->bucket = bucket; - }; -/* - * Increment the reference count of the line. - */ - hnode->used++; - return hnode; -} - -/*....................................................................... - * Decrement the reference count of the history line of a given hash-node, - * and if the count reaches zero, delete both the hash-node and the - * buffered copy of the line. - * - * Input: - * glh GlHistory * The history container object. - * hnode GlhHashNode * The node to be removed. - * Output: - * return GlhHashNode * The deleted hash-node (ie. NULL). - */ -static GlhHashNode *_glh_discard_copy(GlHistory *glh, GlhHashNode *hnode) -{ - if(hnode) { - GlhHashBucket *bucket = hnode->bucket; -/* - * If decrementing the reference count of the hash-node doesn't reduce - * the reference count to zero, then the line is still in use in another - * object, so don't delete it yet. Return NULL to indicate that the caller's - * access to the hash-node copy has been deleted. - */ - if(--hnode->used >= 1) - return NULL; -/* - * Remove the hash-node from the list in its parent bucket. - */ - if(bucket->lines == hnode) { - bucket->lines = hnode->next; - } else { - GlhHashNode *prev; /* The node which precedes hnode in the bucket */ - for(prev=bucket->lines; prev && prev->next != hnode; prev=prev->next) - ; - if(prev) - prev->next = hnode->next; - }; - hnode->next = NULL; -/* - * Return the line segments of the hash-node to the list of unused segments. - */ - if(hnode->head) { - GlhLineSeg *tail; /* The last node in the list of line segments */ - int nseg; /* The number of segments being discarded */ -/* - * Get the last node of the list of line segments referenced in the hash-node, - * while counting the number of line segments used. - */ - for(nseg=1,tail=hnode->head; tail->next; nseg++,tail=tail->next) - ; -/* - * Prepend the list of line segments used by the hash node to the - * list of unused line segments. - */ - tail->next = glh->unused; - glh->unused = hnode->head; - glh->nbusy -= nseg; - glh->nfree += nseg; - }; -/* - * Return the container of the hash-node to the freelist. - */ - hnode = (GlhHashNode *) _del_FreeListNode(glh->hash.node_mem, hnode); - }; - return NULL; -} - -/*....................................................................... - * Private function to locate the hash bucket associated with a given - * history line. - * - * 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: - * glh GlHistory * The history container object. - * line const char * The historical line to look up. - * n size_t The length of the line in line[], excluding - * any '\0' terminator. - * Output: - * return GlhHashBucket * The located hash-bucket. - */ -static GlhHashBucket *glh_find_bucket(GlHistory *glh, const char *line, - size_t n) -{ - unsigned long h = 0L; - int i; - for(i=0; i<n; i++) { - unsigned char c = line[i]; - h = 65599UL * h + c; /* 65599 is a prime close to 2^16 */ - }; - return glh->hash.bucket + (h % GLH_HASH_SIZE); -} - -/*....................................................................... - * Find a given history line within a given hash-table bucket. - * - * Input: - * bucket GlhHashBucket * The hash-table bucket in which to search. - * line const char * The historical line to lookup. - * n size_t The length of the line in line[], excluding - * any '\0' terminator. - * Output: - * return GlhHashNode * The hash-table entry of the line, or NULL - * if not found. - */ -static GlhHashNode *glh_find_hash_node(GlhHashBucket *bucket, const char *line, - size_t n) -{ - GlhHashNode *node; /* A node in the list of lines in the bucket */ -/* - * Compare each of the lines in the list of lines, against 'line'. - */ - for(node=bucket->lines; node; node=node->next) { - if(_glh_is_line(node, line, n)) - return node; - }; - return NULL; -} - -/*....................................................................... - * Return non-zero if a given string is equal to a given segmented line - * node. - * - * Input: - * hash GlhHashNode * The hash-table entry of the line. - * line const char * The string to be compared to the segmented - * line. - * n size_t The length of the line in line[], excluding - * any '\0' terminator. - * Output: - * return int 0 - The lines differ. - * 1 - The lines are the same. - */ -static int _glh_is_line(GlhHashNode *hash, const char *line, size_t n) -{ - GlhLineSeg *seg; /* A node in the list of line segments */ - int i; -/* - * Do the two lines have the same length? - */ - if(n != hash->len) - return 0; -/* - * Compare the characters of the segmented and unsegmented versions - * of the line. - */ - for(seg=hash->head; n>0 && seg; seg=seg->next) { - const char *s = seg->s; - for(i=0; n>0 && i<GLH_SEG_SIZE; i++,n--) { - if(*line++ != *s++) - return 0; - }; - }; - return 1; -} - -/*....................................................................... - * Return non-zero if a given line has the specified segmented search - * prefix. - * - * Input: - * line GlhHashNode * The line to be compared against the prefix. - * prefix GlhHashNode * The search prefix, or NULL to match any string. - * Output: - * return int 0 - The line doesn't have the specified prefix. - * 1 - The line has the specified prefix. - */ -static int _glh_line_matches_prefix(GlhHashNode *line, GlhHashNode *prefix) -{ - GlhLineStream lstr; /* The stream that is used to traverse 'line' */ - GlhLineStream pstr; /* The stream that is used to traverse 'prefix' */ -/* - * When prefix==NULL, this means that the nul string - * is to be matched, and this matches all lines. - */ - if(!prefix) - return 1; -/* - * Wrap the two history lines that are to be compared in iterator - * stream objects. - */ - glh_init_stream(&lstr, line); - glh_init_stream(&pstr, prefix); -/* - * If the prefix contains a glob pattern, match the prefix as a glob - * pattern. - */ - if(glh_contains_glob(prefix)) - return glh_line_matches_glob(&lstr, &pstr); -/* - * Is the prefix longer than the line being compared against it? - */ - if(prefix->len > line->len) - return 0; -/* - * Compare the line to the prefix. - */ - while(pstr.c != '\0' && pstr.c == lstr.c) { - glh_step_stream(&lstr); - glh_step_stream(&pstr); - }; -/* - * Did we reach the end of the prefix string before finding - * any differences? - */ - return pstr.c == '\0'; -} - -/*....................................................................... - * Copy a given history line into a specified output string. - * - * Input: - * hash GlhHashNode The hash-table entry of the history line to - * be copied. - * line char * A copy of the history line. - * dim size_t The allocated dimension of the line buffer. - */ -static void _glh_return_line(GlhHashNode *hash, char *line, size_t dim) -{ - GlhLineSeg *seg; /* A node in the list of line segments */ - int i; - for(seg=hash->head; dim>0 && seg; seg=seg->next) { - const char *s = seg->s; - for(i=0; dim>0 && i<GLH_SEG_SIZE; i++,dim--) - *line++ = *s++; - }; -/* - * If the line wouldn't fit in the output buffer, replace the last character - * with a '\0' terminator. - */ - if(dim==0) - line[-1] = '\0'; -} - -/*....................................................................... - * This function should be called whenever a new line recall is - * attempted. It preserves a copy of the current input line in the - * history list while other lines in the history list are being - * returned. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The current contents of the input line buffer. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _glh_prepare_for_recall(GlHistory *glh, char *line) -{ -/* - * If a recall session has already been started, but we have returned - * to the preserved copy of the input line, if the user has changed - * this line, we should replace the preserved copy of the original - * input line with the new one. To do this simply cancel the session, - * so that a new session is started below. - */ - if(glh->recall && glh->recall == glh->list.tail && - !_glh_is_line(glh->recall->line, line, strlen(line))) { - _glh_cancel_search(glh); - }; -/* - * If this is the first line recall of a new recall session, save the - * current line for potential recall later, and mark it as the last - * line recalled. - */ - if(!glh->recall) { - if(_glh_add_history(glh, line, 1)) - return 1; - glh->recall = glh->list.tail; -/* - * The above call to _glh_add_history() will have incremented the line - * sequence number, after adding the line. Since we only want this to - * to be incremented for permanently entered lines, decrement it again. - */ - glh->seq--; - }; - return 0; -} - -/*....................................................................... - * Return non-zero if a history search session is currently in progress. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * Output: - * return int 0 - No search is currently in progress. - * 1 - A search is in progress. - */ -int _glh_search_active(GlHistory *glh) -{ - return glh && glh->recall; -} - -/*....................................................................... - * Initialize a character iterator object to point to the start of a - * given history line. The first character of the line will be placed - * in str->c, and subsequent characters can be placed there by calling - * glh_strep_stream(). - * - * Input: - * str GlhLineStream * The iterator object to be initialized. - * line GlhHashNode * The history line to be iterated over (a - * NULL value here, is interpretted as an - * empty string by glh_step_stream()). - */ -static void glh_init_stream(GlhLineStream *str, GlhHashNode *line) -{ - str->seg = line ? line->head : NULL; - str->posn = 0; - str->c = str->seg ? str->seg->s[0] : '\0'; -} - -/*....................................................................... - * Copy the next unread character in the line being iterated, in str->c. - * Once the end of the history line has been reached, all futher calls - * set str->c to '\0'. - * - * Input: - * str GlhLineStream * The history-line iterator to read from. - */ -static void glh_step_stream(GlhLineStream *str) -{ -/* - * Get the character from the current iterator position within the line. - */ - str->c = str->seg ? str->seg->s[str->posn] : '\0'; -/* - * Unless we have reached the end of the string, move the iterator - * to the position of the next character in the line. - */ - if(str->c != '\0' && ++str->posn >= GLH_SEG_SIZE) { - str->posn = 0; - str->seg = str->seg->next; - }; -} - -/*....................................................................... - * Return non-zero if the specified search prefix contains any glob - * wildcard characters. - * - * Input: - * prefix GlhHashNode * The search prefix. - * Output: - * return int 0 - The prefix doesn't contain any globbing - * characters. - * 1 - The prefix contains at least one - * globbing character. - */ -static int glh_contains_glob(GlhHashNode *prefix) -{ - GlhLineStream pstr; /* The stream that is used to traverse 'prefix' */ -/* - * Wrap a stream iterator around the prefix, so that we can traverse it - * without worrying about line-segmentation. - */ - glh_init_stream(&pstr, prefix); -/* - * Search for unescaped wildcard characters. - */ - while(pstr.c != '\0') { - switch(pstr.c) { - case '\\': /* Skip escaped characters */ - glh_step_stream(&pstr); - break; - case '*': case '?': case '[': /* A wildcard character? */ - return 1; - break; - }; - glh_step_stream(&pstr); - }; -/* - * No wildcard characters were found. - */ - return 0; -} - -/*....................................................................... - * Return non-zero if the history line matches a search prefix containing - * a glob pattern. - * - * Input: - * lstr GlhLineStream * The iterator stream being used to traverse - * the history line that is being matched. - * pstr GlhLineStream * The iterator stream being used to traverse - * the pattern. - * Output: - * return int 0 - Doesn't match. - * 1 - The line matches the pattern. - */ -static int glh_line_matches_glob(GlhLineStream *lstr, GlhLineStream *pstr) -{ -/* - * Match each character of the pattern until we reach the end of the - * pattern. - */ - while(pstr->c != '\0') { -/* - * Handle the next character of the pattern. - */ - switch(pstr->c) { -/* - * A match zero-or-more characters wildcard operator. - */ - case '*': -/* - * Skip the '*' character in the pattern. - */ - glh_step_stream(pstr); -/* - * If the pattern ends with the '*' wildcard, then the - * rest of the line matches this. - */ - if(pstr->c == '\0') - return 1; -/* - * Using the wildcard to match successively longer sections of - * the remaining characters of the line, attempt to match - * the tail of the line against the tail of the pattern. - */ - while(lstr->c) { - GlhLineStream old_lstr = *lstr; - GlhLineStream old_pstr = *pstr; - if(glh_line_matches_glob(lstr, pstr)) - return 1; -/* - * Restore the line and pattern iterators for a new try. - */ - *lstr = old_lstr; - *pstr = old_pstr; -/* - * Prepare to try again, one character further into the line. - */ - glh_step_stream(lstr); - }; - 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(lstr->c) { - glh_step_stream(lstr); - glh_step_stream(pstr); -/* - * If we hit the end of the line, there is no character - * matching the operator, so the pattern doesn't match. - */ - } else { - return 0; - }; - break; -/* - * A character range operator, with the character ranges enclosed - * in matching square brackets. - */ - case '[': - glh_step_stream(pstr); /* Skip the '[' character */ - if(!lstr->c || !glh_matches_range(lstr->c, pstr)) - return 0; - glh_step_stream(lstr); /* Skip the character that matched */ - break; -/* - * A backslash in the pattern prevents the following character as - * being seen as a special character. - */ - case '\\': - glh_step_stream(pstr); /* Skip the backslash */ - /* Note fallthrough to default */ -/* - * A normal character to be matched explicitly. - */ - default: - if(lstr->c == pstr->c) { - glh_step_stream(lstr); - glh_step_stream(pstr); - } else { - return 0; - }; - break; - }; - }; -/* - * To get here, pattern must have been exhausted. The line only - * matches the pattern if the line as also been exhausted. - */ - return pstr->c == '\0' && lstr->c == '\0'; -} - -/*....................................................................... - * Match a character range expression terminated by an unescaped close - * square bracket. - * - * Input: - * c char The character to be matched with the range - * pattern. - * pstr GlhLineStream * The iterator stream being used to traverse - * the pattern. - * Output: - * return int 0 - Doesn't match. - * 1 - The character matched. - */ -static int glh_matches_range(char c, GlhLineStream *pstr) -{ - int invert = 0; /* True to invert the sense of the match */ - int matched = 0; /* True if the character matched the pattern */ - char lastc = '\0'; /* The previous character in 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(pstr->c == '^') { - glh_step_stream(pstr); - invert = 1; - }; -/* - * The hyphen is only a special character when it follows the first - * character of the range (not including the caret). - */ - if(pstr->c == '-') { - glh_step_stream(pstr); - if(c == '-') - matched = 1; -/* - * Skip other leading '-' characters since they make no sense. - */ - while(pstr->c == '-') - glh_step_stream(pstr); - }; -/* - * The hyphen is only a special character when it follows the first - * character of the range (not including the caret or a hyphen). - */ - if(pstr->c == ']') { - glh_step_stream(pstr); - if(c == ']') - 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 && pstr->c && pstr->c != ']') { -/* - * Is this a range of characters signaled by the two end characters - * separated by a hyphen? - */ - if(pstr->c == '-') { - glh_step_stream(pstr); /* Skip the hyphen */ - if(pstr->c != ']') { - if(c >= lastc && c <= pstr->c) - matched = 1; - }; -/* - * A normal character to be compared directly. - */ - } else if(pstr->c == c) { - matched = 1; - }; -/* - * Record and skip the character that we just processed. - */ - lastc = pstr->c; - if(pstr->c != ']') - glh_step_stream(pstr); - }; -/* - * Find the terminating ']'. - */ - while(pstr->c && pstr->c != ']') - glh_step_stream(pstr); -/* - * Did we find a terminating ']'? - */ - if(pstr->c == ']') { -/* - * Skip the terminating ']'. - */ - glh_step_stream(pstr); -/* - * If the pattern started with a caret, invert the sense of the match. - */ - if(invert) - matched = !matched; -/* - * If the pattern didn't end with a ']', then it doesn't match, - * regardless of the value of the required sense of the match. - */ - } else { - matched = 0; - }; - return matched; -} - diff --git a/libtecla-1.6.1/history.h b/libtecla-1.6.1/history.h deleted file mode 100644 index d32ee8f..0000000 --- a/libtecla-1.6.1/history.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef history_h -#define history_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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, GlWriteFn *write_fn, void *data, - 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); - -/* - * Get information about the last error in this module. - */ -const char *_glh_last_error(GlHistory *glh); - -/* - * Return non-zero if a history search session is currently in progress. - */ -int _glh_search_active(GlHistory *glh); - -#endif diff --git a/libtecla-1.6.1/homedir.c b/libtecla-1.6.1/homedir.c deleted file mode 100644 index eb666c3..0000000 --- a/libtecla-1.6.1/homedir.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/* - * If file-system access is to be excluded, this module has no function, - * so all of its code should be excluded. - */ -#ifndef WITHOUT_FILE_SYSTEM - -#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" -#include "errmsg.h" - -/* - * Use the reentrant POSIX threads versions of the password lookup functions? - */ -#if defined(PREFER_REENTRANT) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L -#define THREAD_COMPATIBLE 1 -/* - * Under Solaris we can use thr_main() to determine whether - * threads are actually running, and thus when it is necessary - * to avoid non-reentrant features. - */ -#if defined __sun && defined __SVR4 -#include <thread.h> /* Solaris thr_main() */ -#endif -#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 { - ErrMsg *err; /* The error message 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) { - errno = ENOMEM; - 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->err = NULL; - home->buffer = NULL; - home->buflen = 0; -/* - * Allocate a place to record error messages. - */ - home->err = _new_ErrMsg(); - if(!home->err) - return _del_HomeDir(home); -/* - * 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) { - errno = ENOMEM; - 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) { - home->err = _del_ErrMsg(home->err); - 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) { - errno = EINVAL; - 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) { - _err_record_msg(home->err, "Can't determine current directory", - END_ERR_MSG); - return NULL; - } - return home_dir; - }; -/* - * When looking up the home directory of the current user, see if the - * HOME environment variable is set, and if so, return its value. - */ - if(login_user) { - home_dir = getenv("HOME"); - if(home_dir) - 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) { - _err_record_msg(home->err, "User '", user, "' doesn't exist.", - END_ERR_MSG); - 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) { - _err_record_msg(home->err, "User '", user, "' doesn't exist.", - END_ERR_MSG); - 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 ? _err_get_msg(home->err) : "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. - * prefix const char * Only information for usernames that - * start with this prefix will be - * returned. Note that the empty - & string "", matches all usernames. - * 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, const char *prefix, - void *data, HOME_DIR_FN(*callback_fn)) -{ - int waserr = 0; /* True after errors */ - int prefix_len; /* The length of prefix[] */ -/* - * Check the arguments. - */ - if(!home || !prefix || !callback_fn) { - if(home) { - _err_record_msg(home->err, - "_hd_scan_user_home_dirs: Missing callback function", - END_ERR_MSG); - }; - return 1; - }; -/* - * Get the length of the username prefix. - */ - prefix_len = strlen(prefix); -/* - * 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(PREFER_REENTRANT) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L -#if defined __sun && defined __SVR4 - if(thr_main() >= 0) /* thread library is linked in */ -#else - if(1) -#endif - { - struct passwd pwd_buffer; /* A returned password entry */ - struct passwd *pwd; /* A pointer to pwd_buffer */ - char buffer[512]; /* The buffer in which the string members of */ - /* pwd_buffer are stored. */ -/* - * See if the prefix that is being completed is a complete username. - */ - if(!waserr && getpwnam_r(prefix, &pwd_buffer, buffer, sizeof(buffer), - &pwd) == 0 && pwd != NULL) { - waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, - _err_get_msg(home->err), ERR_MSG_LEN); - }; -/* - * See if the username of the current user minimally matches the prefix. - */ - if(!waserr && getpwuid_r(getuid(), &pwd_buffer, buffer, sizeof(buffer), - &pwd) == 0 && pwd != NULL && - strncmp(prefix, pwd->pw_name, prefix_len)==0) { - waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, - _err_get_msg(home->err), ERR_MSG_LEN); - }; -/* - * Reentrancy not required? - */ - } else -#endif - { - 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) { - if(strncmp(prefix, pwd->pw_name, prefix_len) == 0) { - waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, - _err_get_msg(home->err), ERR_MSG_LEN); - }; - }; -/* - * Close the password file. - */ - endpwent(); - }; -/* - * Under ksh ~+ stands for the absolute pathname of the current working - * directory. - */ - if(!waserr && strncmp(prefix, "+", prefix_len) == 0) { - const char *pwd = hd_getpwd(home); - if(pwd) { - waserr = callback_fn(data, "+", pwd, _err_get_msg(home->err),ERR_MSG_LEN); - } else { - waserr = 1; - _err_record_msg(home->err, "Can't determine current directory.", - END_ERR_MSG); - }; - }; - 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; -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/homedir.h b/libtecla-1.6.1/homedir.h deleted file mode 100644 index 0ad3e94..0000000 --- a/libtecla-1.6.1/homedir.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef homedir_h -#define homedir_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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, const char *prefix, void *data, - HOME_DIR_FN(*callback_fn)); - -#endif diff --git a/libtecla-1.6.1/html/changes.html b/libtecla-1.6.1/html/changes.html deleted file mode 100644 index 9be5251..0000000 --- a/libtecla-1.6.1/html/changes.html +++ /dev/null @@ -1,2761 +0,0 @@ -<html><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. - -31/10/2004 mcs@astro.caltech.edu (problem reported by Godfrey van der Linden) - getline.c - The gl_event_handler() function had the endif of a - conditional compilation clause in the wrong place. This - only upset the compiler on unusual systems that don't - have select(). The problem was seen under Mac OS X, due - to the configuration problem in 1.6.0 that caused the - configure script to mistakenly report that select wasn't - available. - -31/10/2004 mcs@astro.caltech.edu (info provided by Ivan Rayner) - configure.in configure Makefile.in - Ivan reported that under IRIX 6.5 it is necessary to add - -D_XOPEN_SOURCE=500 to the compiler flags, when compiling - the reentrant version of the library. Thus, whereas - previously I hardwired the value of DEFINES_R in - Makefile.in, I have now made this a variable in the - configure script, which is augmented with the above - addition, within an IRIX-specific switch clause. - - Also apparently configure leaves the RANLIB variable - blank, instead of setting it to ":", so I have now - explicitly set this to ":", within the new IRIX clause of - the configure script. - -31/10/2004 mcs@astro.caltech.edu (info provided by Ivan Rayner) - getline.c - Under IRIX, the compiler warned that gl_read_unmasked() - was returning an int, which was then being assigned to an - enumeration type. This is techically fine, but it - highlighted the fact that I had meant to declare - gl_read_unmasked() to directly return the enumerated - type. I have now done so. - -26/09/2004 mcs@astro.caltech.edu - getline.c - Users can now turn off interactive command-line editing - by setting the TERM environment variable to the word "dumb". - -18/07/2004 mcs@astro.caltech.edu (problem noted by Michael MacFaden) - getline.c - Calling gl_terminal_size() on a system without support - for SIGWINCH caused a divide-by-zero error in an unintended - call to gl_erase_line(), because gl_update_size() was - incorrectly being called to query the terminal size, - instead of gl_query_size(). - -18/07/2004 Padraig Brady (documented here by mcs@astro.caltech.edu) - getline.c - The suspend and termination signal-handlers installed by - gl_tty_signals(), were being installed swapped. - -03/06/2004 Mike Meaney (documented here by mcs@astro.caltech.edu) - getline.c - Mike pointed out the fact that the curses setupterm() - function is actually documented to exit the application - if an error occurs while its optional errret argument is - NULL. I hadn't noticed this, and because I didn't need - the extra information returned in the errret argument, I - was passing it a NULL. As suggested by Mike, I now pass - this argument a pointer to a dummy errret variable. - -23/05/2004 mcs@astro.caltech.edu (problem noted by John Beck) - man/func/cpl_complete_word.in - Some of the prototypes of functions and types documented - by the cpl_complete_word man page, weren't listed in the - Synopsis section of this man page. They are now listed - there. - -23/05/2004 mcs@astro.caltech.edu - getline.c man/func/gl_get_line.in - I have now added support for calling gl_normal_io() from - any callback functions that the application installs by - calling either gl_inactivity_timeout(), or gl_watch_fd(). - Previously, if one of these callback functions called - gl_normal_io(), then after returning to gl_get_line(), - gl_get_line() would incorrectly assume that the terminal - was still in raw I/O mode. Now, gl_get_line() checks to - see if gl_normal_io() was called by the callback, and - if so, calls _gl_raw_io() to reinstate raw I/O mode. - -21/05/2004 mcs@astro.caltech.edu - configure.in configure - On Mac OS X the code that the configure script used to - check for select() failed due to missing symbols in - sys/select.h. Moving the inclusion of sys/select.h to - after the inclusion of sys/time.h, sys/types.h and - sys/unistd.h fixed this. - -11/05/2004 mcs@astro.caltech.edu - getline.c man/func/gl_get_line.in - If the line buffer returned by one call to gl_get_line() - was passed as the start_line argument of the next call to - gl_get_line(), then instead of the just-entered line - being presented back to the user for further editing, the - start_line argument was effectively ignored, because the - line buffer whose pointer was being passed back, was - being cleared before the start_line pointer was examined. - This appears to have been a case of me incorrectly - thinking that I had forgotten to initialize gl->line[] - and gl->ntotal in the gl_reset_input_line() function, and - then "fixing" this supposed omission. Removing this - erroneous fix, restored things to how they were meant to - be. To make it unlikely that I will make the same mistake - again, I have renamed the function from - gl_reset_input_line() to gl_reset_editor(), to stop it - looking as though it is meant to reset the contents of - the input line (that is what gl_truncate_buffer() is - for), explicitly stated that it doesn't clear the input - line, in the header comments of the function, and added a - prominent warning comment in the body of the function. - - Also, since support for passing back the returned line - pointer via the start_line argument of the next call to - gl_get_line(), wasn't documented in the man page, but was - meant to be supported, and definitely used to work, I - have now amended the man page documentation of - gl_get_line() to explicitly state that this feature is - officially supported. - -2?/04/2004 Released 1.6.0 - -22/04/2004 mcs@astro.caltech.edu (Fixed a bug reported by John Beck) - getline.c - When an error, signal, or other abnormal event aborted - gl_get_line(), the cleanup code that restored the - terminal to a sane state, also overwrote the value of - errno that was associated with the aborting event. An - I/O error occurring in the cleanup code would have also - overwritten the value to be returned by - gl_return_status(), and thus remove any possibility of - the caller finding out what really caused gl_get_line() - to abort. I have now written a new internal function - called, gl_record_status(), which records the completion - status to be returned by gl_return_status(), and the - value to assign to errno just before gl_get_line() - returns. This is called wherever code detects conditions - that require gl_get_line() to return early. The function - ensures that once an abnormal completion status has been - recorded for return, subsequent completions statuses - aren't recorded. This ensures that the caller sees the - original cause of the abnormal return, rather than any - error that occurs during cleaning up from this before - return. - -17/04/2004 mcs@astro.caltech.edu - getline.c - If an application's callback called gl_read_char() after - calling gl_normal_io(), it would inappropriately - redisplay the input line, when it called _gl_raw_io() to - temporarily switch the terminal back into raw mode. - - To fix this, _gl_raw_io() now takes a new 'redisplay' - argument, which specifies whether or not to queue a - redisplay of the input line. I also created a new - gl->postpone flag, which is set by gl_normal_io(), and - cleared by _gl_raw_io() (when its redisplay argument is - true). When this flag is set, gl_flush_output() ignores - queued redisplays, as it generally should between calls - to gl_normal_io() and gl_raw_io(). Thus its effect is to - postpone redisplays while line editing is suspended. - -11/04/2004 mcs@astro.caltech.edu - history.c man/misc/tecla.in - History searches can now include the globbing operators - *, ?, []. When a search prefix is found to have at least - one of these characters, then only history lines that - completely match that pattern are returned. - -11/04/2004 mcs@astro.caltech.edu (issue raised by Mark Coiley) - getline.c ioutil.c - There appears to be a bug in Solaris's terminal I/O. - When the terminal file descriptor is placed in - non-blocking I/O mode, and the terminal is switched from - canonical to raw mode, characters that were previously - entered in canonical I/O mode don't become available to - be read until the user types one character more. Select() - incorrectly says that there are no characters available, - and read() returns EAGAIN. This is only a problem for - gl_get_line() when gl_get_line() is in non-blocking - server I/O mode, so most users won't have experienced any - problems with this. - - The only way that I have found to get read() to return - the characters, without the user first having to type - another character, is to turn off non-blocking I/O before - calling read(). Select() still claims that there are no - characters available to be read, but read happily returns - them anyway. Fortunately, one can perform non-blocking - terminal reads without setting the non-blocking I/O flag - of the file descriptor, simply by setting the VTIME - terminal attribute to zero (which I already was - doing). Thus, when in non-blocking server I/O, I now turn - off the non-blocking I/O flag, attempt to read one - character and only if this fails, do I then call the - select() based event handler to implement any configured - non-zero timeout, before attempting the read again. Of - course the non-blocking I/O flag is still needed for - writing, so I only turn it off temporarily while reading. - -25/03/2004 mcs@astro.caltech.edu (bug reported by Gregory Harris) - Makefile.in - It appears that when in February, I patched Makefile.in - to add abolute paths to the install-sh shell-script, - I accidentally replaced install-sh with install.sh. I - corrected the name in the Makefile. - -25/03/2004 Gregory Harris (documented here by mcs) - configure.in configure - Greg added the configuration parameters needed to build - the shared version of the libtecla library under FreeBSD. - -25/03/2004 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man/func/gl_get_line.in - man/func/gl_read_char.in - I wrote a public function called gl_read_char(). Unlike - gl_query_char(), this function neither prompts the user - for input, nor displays the character that was entered. - In fact it doesn't write anything to the terminal, and - takes pains not to disturb any incompletely entered - input line, and can safely be called from application - callback functions. - -21/03/2004 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man/func/gl_get_line.in - man/func/gl_query_char.in - I wrote a public function called gl_query_char(), which - prompts the user and awaits a single-character reply, - without the user having to hit return. - -23/02/2004 mcs@astro.caltech.edu (bug reported by Gregory Harris) - configure.in configure getline.c enhance.c demo3.c - The configure script now checks for the sys/select.h - header file, and arranges for a C macro called - HAVE_SYS_SELECT_H to be set if it exists. Thus the files - that use select() now use this macro to conditionally - include sys/select.h where available. Apparently this - header is required under FreeBSD 5.1. - -23/02/2004 mcs@astro.caltech.edu - getline.c libtecla.h man/func/gl_get_line.in - I wrote two new public functions, gl_append_history() and - gl_automatic_history(). Together these allow the - application to take over the responsibility of adding - lines to the history list from gl_get_line(). I then - documented their functionality in the gl_get_line man - page. - Version 1.6.0 - I incremented the minor version number of the library, to - comply with the requirement to do so when additions are - made to the public interface. See libtecla.map for - details. - libtecla.map - I added a new 1.6.0 group for the new minor version, and - added the above pair of functions to it. - -15/02/2004 mcs@astro.caltech.edu (fixes a bug reported by Satya Sahoo) - history.c - Calling gl_load_history() multiple times, eventually led - to a segmentation fault. This was due to the head of the - list of unused history string segments not getting - reset when the history buffer was cleared. While - debugging this problem I also noticed that the history - resizing function was way too complicated to verify, so - after fixing the above bug, I heavily simplified the - history resizing function, trading off a small reduction - in memory efficiency, for greatly improved clarity, and - thus made it much more verifiable and maintainable. - -14/02/2004 mcs@astro.caltech.edu (fixes a bug reported by Tim Burress). - getline.c - If gl_change_terminal() was first used to tell - gl_get_line to read input from a file, then called later - to tell it to read subsequent input from a terminal, no - prompt would be displayed for the first line of - interactive input. The problem was that on reaching the - end of the input file, gl_get_line() should have called - gl_abandon_line(), to tell the next call to gl_get_line() - to start inputting a new line from scratch. I have added - this now. - -14/02/2004 Krister Walfridsson (documented here by mcs@astro.caltech.edu) - Makefile.in - Krister noticed that I had failed to put $(srcdir)/ in front - of some invokations of install.sh. I have remedied this. - config.guess config.sub - I hadn't updated these for a long time, so apparently they - didn't recognise the BSD system that Krister was using. - I have now updated them to the versions that come with - autoconf-2.59. - -22/01/2004 mcs@astro.caltech.edu - keytab.c - When parsing key-binding specifications, backslash escaped - characters following ^ characters were not being expanded. - Thus ^\\ got interpretted as a control-\ character followed - by a \ character, rather than simply as a control-\ - character. - -12/01/2004 mcs@astro.caltech.edu - cplfile.c cplmatch.c demo2.c demo3.c demo.c direader.c - expand.c getline.c history.c homedir.c pathutil.c pcache.c - configure.in configure INSTALL - The configuration script now takes a - "--without-file-system" argument. This is primarily for - intended for embedded systems that either don't have - filesystems, or where the file-system code in libtecla is - unwanted bloat. It sets the WITHOUT_FILE_SYSTEM - macro. This removes all code related to filesystem - access, including the entire public file-expansion, - file-completion and path-lookup facilities. Note that the - general word completion facility is still included, but - without the normally bundled file completion - callback. Actually the callback is still there, but it - reports no completions, regardless of what string you ask - it to complete. - - This option is described in the INSTALL document. - -12/01/2004 mcs@astro.caltech.edu - getline.c configure.in configure INSTALL - The configuration script now takes a - "--without-file-actions" argument. This allows an - application author/installer to prevent users of - gl_get_line() from accessing the filesystem from the - builtin actions of gl_get_line(). It defines a macro - called HIDE_FILE_SYSTEM. This causes the - "expand-filename", "read-from-file", "read-init-files", - and "list-glob" action functions to be completely - removed. It also changes the default behavior of actions - such as "complete-word" and "list-or-eof" to show no - completions, instead of the normal default of showing - filename completions. - - This option is described in the INSTALL document. - -11/01/2004 mcs@astro.caltech.edu - getline.c man/func/gl_get_line.in - In case an application's customized completion handler - needs to write to the terminal for some unforseen reason, - there needs to be a way for the it to cleanly suspend raw - line editing, before writing to the terminal, and the - caller then needs to be aware that it may need to - resurrect the input line when the callback returns. I - have now arranged that the completion callback functions - can call the gl_normal_io() function for this purpose, - and documented this in the gl_get_line() man page. - -11/01/2004 mcs@astro.caltech.edu (In response to a bug report by Satya Sahoo) - getline.c - The gl_configure_getline() function makes a malloc'd copy - of the names of the configuration files that it is asked - to read. Before the bug fix, if the application made one - or more calls to this function, the memory allocated by - the final call that it made before calling del_GetLine(), - wasn't being freed. Note that memory allocated in all but - the final call was being correctly freed, so the maximum - extent of the memory leak was the length of the file - name(s) passed in the final call to - gl_configure_getline(), and an application that didn't - call gl_configure_getline() didn't suffer any leak. - -20/12/2003 mcs@astro.caltech.edu - history.c - Ellen tested the history fix that I reported below, and - pointed out that it still had a problem. This turned out - to be because getline.c was making some incorrect - assumptions about the new behavior of history.c. This - problem and the previous one both revolved around how - search prefixes were stored and discarded, so I have now - re-written this part of the code. Previously the search - prefix was retained by looking for a line with that - prefix, and keeping a pointer to that line. This saved - memory, compared to storing a separate copy of the - prefix, but it led to all kinds of hairy - interdependencies, so I have now changed the code to keep - a separate copy of search prefixes. To keep the memory - requirements constant, the search prefix is stored in the - history buffer, like normal history lines, but not - referenced by the time-ordered history list. The prefix - can now be kept around indefinitely, until a new search - prefix is specified, regardless of changes to the - archived lines in the history buffer. This is actually - necessary to make the vi-mode re-search actions work - correctly. In particular, I no longer discard the search - prefix whenever a history search session ends. Also, - rather than have getline.c keep its own record of when a - history session is in progress, it now consults - history.c, so that failed assumptions can't cause the - kind of discrepancy that occurred before. For this to - work, getline.c now explicitly tells history.c to cancel - search sessions whenever it executes any non-history - action. - -14/12/2003 mcs@astro.caltech.edu (bug reported by Ellen Oschmann) - history.c - If one searched backwards for a prefix, then returned to - the original line, changed that line, then started - another backwards prefix search, getline incorrectly - discarded the new search prefix in the process of - throwing away its cached copy of the previous pre-search - input line. In other words getline was belatedly - cancelling a previous search, after a new search had - already partially begun, and thus messed up the new - search. The obvious fix was to arrange for the current - search to be cancelled whenever the history pointer - returns to its starting point, rather than waiting for - the next search to begin from there. - -14/12/2003 mcs@astro.caltech.edu - history.c - _glh_recall_line() was returning the last line in the - history buffer instead of the line requested by the - caller. This only affected the obscure "repeat-history" - action-function, which probably isn't used by anybody. - -09/12/2003 Version 1.5.0 released. - -28/09/2003 mcs@astro.caltech.edu - homedir.c - When the home directory of the login user is requested, - see if the HOME environment variable exists, and if so - return its value, rather than looking up the user's home - directory in the password file. This seems to be the - convention adopted by other unix programs that perform - tilde expansion, and it works around a strange problem, - where a third-party libtecla program, statically compiled - under an old version of RedHat, unexpectedly complained - that getpwd() returned an error when the program was run - under RedHat 9. - -01/09/2003 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man/func/gl_get_line.in - man/func/gl_register_action.in. - It is now possible for an application to register - external functions as action functions. These actions are - initially bound to specified key-sequences, but if they - are registered before the user's configuration file is - loaded, they can also be re-bound by the user to - different key-sequences. The function used to register a - new action, is called gl_register_action(). Action - functions are passed a readonly copy of the input line - and the cursor position. They can display text to the - terminal, or perform other operations on the application - environment. Currently, they can't edit the input line or - move the cursor. This will require the future addition of - functions to queue the invokation of the built-in action - functions. - -26/08/2003 mcs@astro.caltech.edu - getline.c - I modified gl_update_buffer() to ensure that the cursor - stays within the input line after external line - modifications, and to queue a redisplay of the - potentially modified input line. - -21/07/2003 mcs@astro.caltech.edu - configure.in configure Makefile.in Makefile.stub INSTALL - By specifying --without-man-pages or --with-man-pages=no - as command-line arguments to the configure script, it is - now possible to have the configure script skip the - man-page preprocessing step, and arrange for the man-page - installation targets in the Makefile to do nothing. This - option is designed for people who embed libtecla within - other packages. It is also used by Makefile.stub when - the distclean target is specified. - -21/07/2003 mcs@astro.caltech.edu - configure.in configure - The previous workaround for recent versions of gcc - placing /usr/local/include at the start of the system - inlcude-file search path, broke something else. The fix - placed /usr/include before gcc's include area, which - meant that gcc's modified version of stdarg.h was being - ignored in deference to the version in /usr/include. I - have changed the fix to have gcc report the search path, - then have awk add options to CFLAGS to reorder this path, - plaing /usr/local/include at the end. - - Also, under Solaris 9, including term.h without first - including curses.h results in complaints about undefined - symbols, such as bool. As a result the configure script's - test for term.h was failing. I have now modified it to - include curses.h in the test code that it uses to check - for term.h. In the process I also improved the tests for - curses.h and term.h to prevent an ncurses version of - term.h from being used with the system-default version of - curses.h. - -29/06/2003 mcs@astro.caltech.edu - Makefile.in direader.c homedir.c - On some systems (eg. linux) the _POSIX_C_SOURCE - feature-test macro is set by system headers, rather than - being an option set by a project's Makefile at - compilation time. In software, such as tecla, where the - definition of this macro is used as an indication of - whether to use the non-reentrant or reentrant versions of - system functions, this means that the reentrant functions - are always used, regardless of whether this macro is set - or not by the project Makefile. Thus, on such systems the - reentrant and non-reentrant versions of the tecla library - are essentially identical. This has a couple of - drawbacks. First, since thread-safe functions for - traversing the password file don't exist, the supposedly - non-reentrant version of the tecla library can't support - ambiguous tab-completion of usernames in ~username/ - constructions. Secondly, on some systems the use of - reentrant system functions dictates the use of a shared - library that isn't needed for the non-reentrant - functions, thus making it more difficult to distribute - binary versions of the library. - - To remedy this situation I have modified the DEFINES_R - variable in Makefile.in to arrange for the compiler to - define a C macro called PREFER_REENTRANT when it is - compiling the reentrant version of the tecla library. - This macro is now used in the source code to determine - when to require reentrant code. Whithin the source code, - wherever a potentially non-reentrant interface is used, - the existance of both this macro and a suitably valued - _POSIX_C_SOURCE macro, are tested for to see if a - reentrant alternative to the problem code should be used. - -22/06/2003 mcs@astro.caltech.edu - getline.c - I changed the way that redisplays are requested and - performed. Redisplays are now queued by calling - gl_queue_redisplay(), and subsequently performed by - gl_flush_output(), when the queue of already pending - output has been completely dispatched. This was necessary - to prevent event handlers from filling up the output - queue with redisplays, and it also simplifies a number of - things. In the process I removed the gl_queue_display() - function. I also wrote a gl_line_erased() function, which - is now called by all functions that erase the input - line. I also split the gl_abandon_line() function into - public and private callable parts, and used the private - version internally to arrange to discard the input line - after errors. - - The raw_mode flag was not being initialized by new_GetLine(). - It is now initialized to zero. - - I removed the zapline flag, since using the endline flag to - communicate the desire to terminate the line, did the same - thing. - - gl_terminal_move_cursor() now does nothing when the input - line isn't displayed. - -18/03/2003 mcs@astro.caltech.edu - getline.c - Fixed bug which was causing newlines not to be output - at the end of each newly entered line. I was - interpreting the gl->endline flag in conflicting ways in - two places. To fix this I have created a gl->displayed - flag. This flags whether an input line is currently - displayed. - -17/03/2003 mcs@astro.caltech.edu - getline.c libtecla.h man/func/gl_get_line.in - man/func/gl_erase_terminal.in libtecla.map - I added a new function that programs can call to clear - the terminal between calls to gl_get_line(). - -11/03/2003 mcs@astro.caltech.edu - configure.in configure - Under linux when _POSIX_C_SOURCE is defined, getpwent() - and associated functions become undefined, because - _SVID_SOURCE and _BSD_SOURCE become undefined. Adding - these feature macros back to CFLAGS resolves this. - -06/03/2003 mcs@astro.caltech.edu - getline.c libtecla.map man/func/gl_get_line.in - Following the lead of Edward Chien, I wrote a function - called gl_bind_keyseq(), which binds a specified - key-sequence to a given action, or unbinds the - key-sequence. - -24/02/2003 mcs@astro.caltech.edu - getline.c libtecla.map man/func/cpl_complete_word.in - I implemented a simple function called - cpl_recall_matches(). This recalls the return value of - the last call to cpl_complete_word(). - -19/01/2003 mcs@astro.caltech.edu - getline.c - The documented signal handling, fd event-handling, - inactivity timeout handling, and server-mode non-blocking - I/O features are now implemented for non-interactive - input streams, such as pipes and files. - -19/01/2003 mcs@astro.caltech.edu - getline.c libtecla.h man/func/gl_get_line.in demo3.c - I added a new return status enumerator to report - when an end-of-file condition causes gl_get_line() - to return NULL. - -13/01/2003 mcs@astro.caltech.edu - history.c - I rewrote the history facility. The previous - circular buffer implementation was a nightmare to change, - and it couldn't efficiently support certain newly - requested features. The new implementation stores history - lines in linked lists of fixed sized string segments, - taken from the buffer, with each line being reference - counted and recorded in a hash table. If the user enters - a line multiple times, only one copy of the line is now - stored. Not only does this make better use of the - available buffer space, but it also makes it easy to - ensure that a line whose prefix matches the current - search prefix, isn't returned more than once in sequence, - since we can simply see if the latest search result has - the same hash-table pointer as the previous one, rather - than having to compare strings. Another plus is that due - to the use of linked lists of nodes of fixed size line - segments, there is no longer any need to continually - shuffle the contents of the buffer in order to defragment - it. As far as the user is concerned, the visible - differences are as follows: - - 1. If the user enters a given line multiple times in a - row, each one will be recorded in the history list, - and will thus be listed by gl_show_history(), and - saved in the history file. Previously only one line - was recorded when consecutive duplicates were entered. - This was a kludge to prevent history recall from - recalling the same line multiple times in a row. This - only achieved the desired result when not recalling by - prefix. - - 2. Not only simple recall, but prefix-based history line - recalls now don't return the same line multiple times - in a row. As mentioned in (1) above, previously this - only worked when performing a simple recall, without a - search prefix. - -28/12/2002 mcs@astro.caltech.edu - getline.c - The one-line function, gl_buff_curpos_to_term_curpos() - was only being used by gl_place_cursor(), so I inlined it - in that function, and removed it. - -28/12/2002 mcs@astro.caltech.edu - getline.c - gl_suspend_process() was calling the application-level - gl_normal_io() and gl_raw_io() functions, where it should - have been calling the internal versions _gl_normal_io() - and _gl_raw_io(). - Also gl_handle_signal() was masking and unmasking just - the signals of the first element of the gl[] array - argument. It now masks and unmasks all trappable signals. - -28/12/2002 mcs@astro.caltech.edu - getline.c - Now that the number of terminal characters used to - display the current input line, is recorded, the relative - line on which the last character of the input line - resides can be determined without having to call - gl_buff_curpos_to_term_curpos(). This is now used by - gl_normal_io() via gl_start_newline(), so there is now no - need for gl_buff_curpos_to_term_curpos() to be - async-signal safe. I have thus removed the annoying - gl->cwidth[] array, and gl_buff_curpos_to_term_curpos() - now calls gl_width_of_char() directly again. There is - also now no need for the gl_line_of_char_start() and - gl_line_of_char_end() functions, so I have removed them. - -28/12/2002 mcs@astro.caltech.edu - getline.c - Unfortunately it turns out that the terminfo/termcap - control sequence which is defined to delete everything - from the current position to the end of the terminal, is - only defined to work when at the start of a terminal - line. In gnome terminals in RedHat 8.0, if it is used - within a terminal line, it erases the whole terminal - line, rather than just what follows the cursor. Thus to - portably truncate the displayed input line it is - necessary to first use the control sequence which deletes - from the cursor position to the end of the line, then if - there are more terminal lines, move to the start of the - next line, and use the delete to end-of-terminal control - sequence, then restore the cursor position. This requires - that one know how many physical terminal lines are used - by the current input line, so I now keep a record of the - number of characters so far displayed to the terminal - following the start of the prompt, and the new - gl_truncate_display() function uses this information to - truncate the displayed input line from the current cursor - position. - -28/12/2002 mcs@astro.caltech.edu - getline.c - gl_start_newline() now moves to an empty line following - the input line, rather than just to the next line. It - also arranges for the input line to be redisplayed before - editing resumes. A major user of this is gl_print_info(), - which now need not be followed by an explicit call to - gl_redisplay(), since the terminal input loop in - gl_get_input_line() ensures that gl_redisplay() is called - after any action function that asserts gl->redisplay. - Also, all functions that erase the displayed input line - can now call the gl_erase_line() function, which is - designed to work correctly even when a terminal resize - invalidates the horizontal cursor position. Finally, the - new gl_queue_display() function is now used by functions - that need to arrange for the input line to be displayed - from scratch after the displayed line has been erased or - invalidated by other text being written to the terminal. - All of these changes are aimed at reducing the number of - places that directly modify gl->term_curpos and - gl->redisplay. - -22/12/2002 Markus Gyger (logged here by mcs) - Makefile.in update_html - In places where echo and sed were being used to extract - the base names of files, Markus substituted the basename - command. He also replaced explicit cp and chmod commands - with invokations of the install-sh script. - configure.in - Use $target_os and $target_cpu, where appropriate, - instead of $target. - configure.in - The Solaris man function and library man pages should - be in sections 3lib and 3tecla respectively, only in - Solaris version 2.8 and above. - configure.in - Markus provided values for the man page configuration - variables for HPUX. - man/*/*.in - I had missed parameterizing man page section numbers in - the man page titles, Markus corrected this. - man/func/libtecla_version.in - Fixed incorrect section number in the link to the - libtecla man page. - homedir.c - When compiled to be reentrant, although one can't use the - non-reentrant getpwent() function to scan the password - file for username completions, one can at least see if - the prefix being completed is a valid username, and if - the username of the current user minimally matches the - prefix, and if so list them. I simplified Markus' - modification by adding a prefix argument to the - _hd_scan_user_home_dirs() function, and redefining the - function description accordingly, such that now it - reports only those password file entries who's usernames - minimally match the specified prefix. Without this, it - would have been necessary to peak inside the private data - argument passed in by cf_complete_username(). - Markus also provided code which under Solaris uses the - non-reentrant interfaces if the reentrant version of the - library isn't linked with the threads library. - -19/12/2002 mcs@astro.caltech.edu - Makefile.in - Markus pointed out that LDFLAGS was being picked up by - the configure script, but not then being interpolated - into te Makefile. I have thus added the necessary - assignment to Makefile.in and arranged for the value of - LDFLAGS to be passed on to recursive make's. I also did - the same for CPPFLAGS, which had also been omitted. - -18/12/2002 mcs@astro.caltech.edu - man/* man/*/* configure.in configure Makefile.in - update_html - It turns out that the assignment of man page sections to - topics differs somewhat from system to system, so this is - another thing that needs to be configured by the main - configuration script, rather than being hardwired. All - man pages have now been moved into suitably named - topic-specific sub-directories of the top-level man - directory, and instead of having a numeric suffix, now - have the .in suffix, since they are now preprocessed by - the configure script, in the same fashion as Makefile.in. - Whithin these *.in versions of the man pages, and within - Makefile.in, the installation subdirectory (eg. man1) and - the file-name suffix (eg. 1), are written using - configuration macros, so that they get expanded to the - appropriate tokens when the configure script is run. In - principle, the man pages could also take advantage of - other configuration macros, such as the one which expands - to the library installation directory, to include full - path names to installed files in the documentation, so in - the future this feature could have more uses than just - that of parameterizing man page sections. - -18/12/2002 mcs@astro.caltech.edu - man3 man3/* Makefile.in html/index.html update_html - Markus suggested splitting the gl_get_line(3) man page - into user and developer sections, and also pointed out - that the enhance man page should be in section 1, not - section 3. I have thus created a top-level man - directory in which to place the various sections, and - moved the man3 directory into it. The enhance.3 man page - is now in man/man1/enhance.1. I have extracted all - user-oriented sections from the gl_get_line(3) man page - and placed them in a new man7/tecla.7 man page. - -18/12/2002 mcs@astro.caltech.edu - getline.c - Terminal resizing was broken in normal mode, due to - me forcing the terminal cursor position to zero in the - wrong place in gl_check_caught_signal(). - -14/12/2002 Markus Gyger (logged here by mcs) - configure.in configure - Under Solaris, recent versions of gcc search - /usr/local/include for header files before the system - directories. This caused a problem if ncurses was - installed under Solaris, since the termcap.h include file - in /usr/local/include ended up being used at compile - time, whereas the system default version of the curses - library was used at link time. Since the two libraries - declare tputs() differently, this evoked a complaint from - gcc. Markus came up with a way to force Gnu cpp to move - /usr/local/include to the end of the system-include-file - search path, where it belongs. - -13/12/2002 mcs@astro.caltech.edu - man3/gl_io_mode.3 - I rewrote the man page which documents the new non-blocking - server I/O mode. - -12/12/2002 mcs@astro.caltech.edu - demo3.c - I wrote a new version of demo3.c, using signal handlers - that call gl_handle_signal() and gl_abandon_line(), where - previously in this demo, these functions were called from - the application code. - -05/12/2002 mcs@astro.caltech.edu - getline.c - gl_normal_io(), gl_raw_io() and gl_handle_signal() and - gl_abandon_line() are now signal safe, provided that - signal handlers that call them are installed with sa_mask's - that block all other signals who's handlers call them. - This is the case if gl_tty_signals() is used to install - signal handlers that call any of these functions. - - A major stumbling block that had to be overcome was that - gl_displayed_char_width() calls isprint(), which can't - safely be called from a signal handler (eg. under linux, - the is*() functions all use thread-specific data - facilities to support per-thread locales, and the - thread-specific data facilities aren't signal safe). To - work around this, all functions that modify the - input-line buffer, now do so via accessor functions which - also maintain a parallel array of character widths, for - use by gl_buff_curpos_to_term_curpos() in place of - gl_displayed_char_width(). Other minor problems were the - need to avoid tputs(), who's signal safety isn't defined. - -05/12/2002 Eric Norum (logged here by mcs@astro.caltech.edu) - configure.in - Eric provided the configuration information needed - to build shared libraries under Darwin (Max OS X). - -05/12/2002 Richard Mlynarik (logged here by mcs@astro.caltech.edu) - configure.in - AC_PROG_RANLIB gets the wrong version of ranlib when - cross compiling, so has now been replaced by an - invokation of AC_CHECK_TOOL. In addition, AC_CHECK_TOOL - is also now used to find an appropriate version of LD. - -05/12/2002 mcs@astro.caltech.edu (based on patch by Pankaj Rathore) - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - The new gl_set_term_size() function provides a way - to tell gl_get_line() about changes in the size of - the terminal in cases where the values returned by - ioctl(TIOCGWINSZ) isn't correct. - -05/12/2002 mcs@astro.caltech.edu - getline.c - Rather than calling sprintf() to see how much space would - be needed to print a given number in octal, I wrote a - gl_octal_width() function, for use by - gl_displayed_char_width(). This makes the latter - function async signal safe. - -05/12/2002 mcs@astro.caltech.edu - chrqueue.c - Whenever the buffer is exhausted, and getting a new - buffer node would require a call to malloc(), attempt - to flush the buffer to the terminal. In blocking I/O - mode this means that the buffer never grows. In - non-blocking I/O mode, it just helps keep the buffer - size down. - -05/12/2002 mcs@astro.caltech.edu - freelist.h freelist.c - The new _idle_FreeListNodes() function queries the - number of nodes in the freelist which aren't currently - in use. - -05/12/2002 mcs@astro.caltech.edu - Makefile.stub - This now accepts all of the targets that the configured - makefile does, and after configuring the latter makefile, - it invokes it with the same options. - -03/12/2002 mcs@astro.caltech.edu - mans3/gl_io_mode.3 - I completed the man page for all of the new functions - related to non-blocking I/O. - -01/12/2002 mcs@astro.caltech.edu - man3/gl_get_line.3 - I wrote a long section on reliable signal handling, - explaining how gl_get_line() does this, how to make - use of this in a program, and how to handle signals - reliably when faced with other blocking functions. - This basically documents what I have learnt about - signal handling while working on this library. - -01/12/2002 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - In non-blocking server mode, the gl_replace_prompt() - function can now be used between calls to gl_get_line() - if the application wants to change the prompt of the - line that is being edited. - -01/12/2002 mcs@astro.caltech.edu - man3/gl_get_line.3 - I documented the new gl_return_status() and - gl_error_message() functions. - -01/12/2002 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - Added SIGPOLL and SIGXFSZ to the list of signals that - are trapped by default. These are process termination - signals, so the terminal needs to be restored to a - usable state before they terminate the process. - -27/11/2002 mcs@astro.caltech.edu - getline.c libtecla.h - Completed the essential changes needed to support - non-blocking server-I/O mode. - - The new gl_io_mode() function allows one to switch to - and from non-blocking server-I/O mode. - - The new gl_raw_io() function is used in non-blocking - server-I/O mode to switch the terminal into non-blocking - raw I/O mode. - - The new gl_normal_io() function is used in non-blocking - server-I/O mode to switch the restore the terminal to - a normal, blocking state. This is used to suspend line - input before suspending the process or writing messages - to the terminal. - - The new gl_tty_signals() function installs specified - signals handlers for all signals that suspend, terminate - or resume processes, and also for signals that indicate - that the terminal has been resized. This not only saves - the application from having to keep its own ifdef'd list - of such signals, of which there are many, but it also - makes sure that these signal handlers are registered - correctly. This includes using the sa_mask member of each - sigaction structure to ensure that only one of these - handlers runs at a time. This is essential to avoid the - signal handlers all trying to simultaneously modify - shared global data. - - The new gl_handle_signal() function is provided for - responding (from application level) to signals caught by - the application. It handles process suspension, process - termination and terminal resize signals. - - The new gl_pending_io() function tells the application - what direction of I/O gl_get_line() is currently waiting - for. - - In non-blocking server I/O mode, the new - gl_abandon_line() function can be called between calls to - gl_get_line() to discard an input line and force the next - call to gl_get_line() to start the input of a new line. - - Also, in non-blocking server-I/O gl_get_line() doesn't - attempt to do anything but return when one of the signals - that it is configured to catch is caught. This is - necessary because when in this mode, the application is - required to handle these signals when gl_get_line() is - running, and the default configuration of most of these - signals in gl_get_line() is to restore the terminal then - call the application signal handlers. This would be a - case of too many cooks spoiling the broth, so in this - mode, gl_get_line() always defers to the application's - signal handlers. - -26/11/2002 mcs@astro.caltech.edu - getline.c libtecla.h - I implemented a couple of new functions to support - reliable signal handling, as now documented - (see above) in the gl_get_line(3) man page. - - The new gl_catch_blocked() function tells gl_get_line() - to unblock all configured signals around calls to - long-running functions, not only those that aren't - blocked when gl_get_line() is called. This allows - the caller to implement reliable signal handling, - since the unblocking is only done from within code - protected by sigsetjmp(), which avoids race conditions. - - The new gl_list_signals() function fills a provided - sigset_t with the set of signals that gl_get_line() is - currently configured to catch. This allows callers to - block said signals, such that they are only unblocked by - gl_get_line() when it is waiting for I/O. When used in - conjunction with the gl_catch_blocked() function, this - removes the potential for race conditions. - - Also, when gl_get_line() installs its signal handler, - it uses the sa_mask member of the sigaction structure - to ensure that only one instance of this signal handler - will ever be executing at a time. - -25/11/2002 mcs@astro.caltech.edu (bug reported by Pankaj Rathore) - getline.c - When any history recall action was invoked when the - input line buffer was full, an error message would be - displayed complaining about the length of the string - in the line input buffer being inconsistent with the - specified allocated size. This was because instead of - sending the allocated size of the input line, I was - sending the length excluding the element that is - reserved for the '\0' terminator. Sending it the - correct size corrected the problem. - -24/11/2002 mcs@astro.caltech.edu - getline.c - All public functions which take GetLine objects as - arguments now block signals on entry and restore the - signal mask on return. This was an attempt to make it - safe to call getline functions from signal handlers, but - the fact is that the functions that I really wanted this - to apply to, potentially call malloc(), so this currently - isn't the case. - -23/11/2002 mcs@astro.caltech.edu - getline.c libtecla.h - The new gl_return_status() function returns an enumerated - return status which can be used to query what caused - gl_get_line() to return. - -22/11/2002 mcs@astro.caltech.edu - Most existing .c and .h files, plus errmsg.c errmsg.h - Makefile.rules - Until now, many library functions would report error - messages to stderr. This isn't appropriate for library - functions, so in place of this behavior, error messages - are now recorded in internal ErrMsg objects, and passed - between modules via new module-specific error querying - functions. In addition, errno is now set appropriately. - Thus when gl_get_line() and related functions return an - error, strerror() can be used to look up system errors, - and gl_error_message() can be used to recover a higher level - error message. Note that error messages that are - responses to user actions continue to be reported to the - terminal, as before. - -21/11/2002 mcs@astro.caltech.edu - getline.c keytab.h keytab.c Makefile.rules - I wrote a new version of _kt_lookup_binding() that didn't - require the caller to have access to the innards of a - KeyTab object. This then enabled me to move the definition - of KeyTab objects into keytab.c and make the typedef in - keytab.h opaque. Many nested includes were also moved from - keytab.h into keytab.c. - -05/11/2002 mcs@astro.caltech.edu - getline.c libtecla.map libtecla.h demo3.c - I split the old gl_resize_terminal() function into - two parts, gl_query_size() and gl_update_size(), with - the latter calling the former to get the new terminal - size. - -05/11/2002 mcs@astro.caltech.edu - getline.c - I fixed a long time bug in the terminal resizing code. - When the cursor wasn't on the last terminal line of the - input line, the resizing code would redisplay the - the line one or more lines above where it should be - restored. This was due to an error in the calculation of - the number of lines above the cursor position. - -04/11/2002 mcs@astro.caltech.edu - demo.c demo2.c demo3.c - I used the new gl_display_text() function to display - introductory text at the startup of each of the demo - programs. The text is enclosed within a box of asterixes, - drawn dynamically to fit within the confines of the - available terminal width. - -04/11/2002 mcs@astro.caltech.edu - libtecla.h getline.c ioutil.c ioutil.h Makefile.rules - libtecla.map man3/gl_get_line.3 man3/gl_display_text.3 - Needing a way to display introductory text intelligently - in the demo programs, I wrote and documented the - gl_display_text() function. This justifies arbitrary - length text within the bounds of the terminal width, - with or without optional indentation, prefixes and - suffixes. - -03/11/2002 mcs@astro.caltech.edu - demo3.c Makefile.rules - I wrote a new demonstration program. This program acts - exactly like the main demonstration program, except that - it uses an external event loop instead of using the - gl_get_line() internal event loop. This is thus an example - of the new non-blocking server I/O facility. - -02/11/2002 mcs@astro.caltech.edu - getline.c keytab.c keytab.h libtecla.h man3/gl_get_line.3 - man3/gl_completion_action.3 - I added the ability to register additional word - completion actions via the new function - gl_completion_action(). All action functions now take a - new (void *data) argument, which is stored with the - function in the symbol table of actions. The new - gl_completion_action() function uses this feature to - record dynamically allocated objects containing the - specified completion function and callback data along - with either the gl_complete_word() action function, or - the gl_list_completions() action function. These two - actions continue to use the builtin completion functions - when their data pointer is NULL. - -20/10/2002 mcs@astro.caltech.edu - The following are changes merged from the non-blocking - gl_get_line() development branch. - - getline.c - I wrote a gl_start_newline() function, to replace all of - the explicit calls to output \r\n to stdout. - - Informational messages are now written to the terminal - using a new variadic function called gl_print_info(). - This starts a newline, writes string arguments until a - special argument, GL_END_INFO, is seen, then starts - another newline. - - Changed _output_ to _print_ in the following function - names gl_output_control_sequence(), gl_output_char(), - gl_output_string() and gl_output_raw_string(). - - gl_print_raw_string() now has a length argument, so that - strings that aren't terminated with '\0' can be printed. - - The display of the initial contents of a new line to be - edited has been moved into a new function called - gl_present_line(). - - The gl_get_input_line() function now takes the prompt - string as an argument so that gl_replace_prompt() can be - called from within this function instead of from - gl_get_line(). - - Keyboard input is now buffered in a persistent buffer in - the parent GetLine object. gl_read_character() checks - this for unprocessed characters in preference to calling - gl_read_terminal() to append characters to it. A new - function, gl_discard_chars(), removes processed - characters from this buffer. This change is in - preparation for a non-blocking version of gl_get_line(), - where partially input key-sequences must be stored - between calls to gl_get_line(). - - getline.c getline.h history.c history.h cplmatch.c \ - cplmatch.h expand.c expand.h - All terminal output from gl_get_line() is now routed - through a GL_WRITE_FN() callback function called - gl_write_fn. Internal functions in cplmatch.c, - expand.c and history.c have been created which take - such callbacks to write output. These are used both - by functions in getline.c, to display file completions, - expansions, history etc, and as the internals of existing - public functions in these files that print to stdio - streams. In the latter case an internal stdio - GL_WRITE_FN() callback is substituted, so that the - functions behave as before. - - getline.c chrqueue.c chrqueue.h - The gl_write_fn() callback used by gl_get_line() now - writes to a queue, implemented in chrqueue.c. This queue - is implemented as a list of blocks of buffer segments, - the number of which shrink and grow as - needed. The contents of the queue are flushed to the - terminal via another GL_WRITE_FN() callback passed to the - queue object. Currently gl_get_line() passes an internal - function assigned to gl->flush_fn, called - gl_flush_terminal(), which writes the contents of the - queue to the terminal, and knows how to handle both - blocking and non-blocking I/O. The output queue is - designed to be flushed to the terminal incrementally, and - thereby also facilitates non-blocking I/O. - - getline.c getline.h - gl_get_line() now reads all input via the GL_READ_FN() - callback, assigned to gl->read_fn. Currently this is - set to an internal function called gl_read_terminal(), - which knows how to handle both blocking and - non-blocking I/O. - - getline.c libtecla.h - The new gl_set_nonblocking() function can be used to - enable or disable non-blocking I/O. The default is still - blocking I/O. In non-blocking mode, the terminal is told - not to wait when either reading or writing would block. - gl_get_line() then returns, with a return value of NULL, - but with the terminal left in raw mode, so that the - caller's event loop can detect key presses. The caller - should call gl_return_status() to check whether the NULL - return value was due to an error, lack of input, or - inability to write to the terminal without waiting. If - either reading or writing was said to have blocked, the - user then should check for I/O readiness in the specified - direction before calling gl_get_line() again to - incrementally build up the input line. - -05/08/2002 mcs@astro.caltech.edu - man3/gl_get_line.3 man3/gl_inactivity_timeout.3 - I documented the new gl_inactivity_timeout() function. - -08/07/2002 mcs@astro.caltech.edu - libtecla.h getline.c libtecla.map - I added a new gl_inactivity_timeout() function. On - systems that have the select system call, this provides - the option of registering a function that is then called - whenever no I/O activity has been seen for more than a - specified period of time. Like the gl_watch_fd() - facility, timeout callbacks return a code which tells - gl_get_line() how to proceed after the timeout has been - handled. - -04/07/2002 mcs@astro.caltech.edu (based on a bug report from Michael MacFaden) - getline.c - The internal event handler wasn't responding to write - events on client file descriptors, due to a typo which - resulted in read events being checked for twice, and - writes not checked for at all. - pathutil.c - The amount of space to allocate for pathnames is supposed - to come from PATH_MAX in limits.h, but I had neglected to - include limits.h. This went unnoticed because on most - systems the equivalent number is deduced by calling - pathconf(). Apparently under NetBSD this function doesn't - work correctly over NFS mounts. - -30/05/2002 Version 1.4.1 released. - -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. - -07/05/2002 mcs@astro.caltech.edu (async development branch only) - getline.c - gl_read_character() now caches and reads unprocessed - characters from a key-press lookahead buffer. Whenever - gl_intepret_char() receives a new character which makes - an initially promising key-sequence no longer match the - prefix of any binding, it now simply discards the first - character from the key-press buffer and resets the buffer - pointer so that the next call to gl_read_character() - returns the character that followed it, from the buffer. - getline.c - The part of gl_get_input_line() which preloads, displays - and prepares to edit a new input line, has now been moved - into a function called gl_present_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></html> diff --git a/libtecla-1.6.1/html/cpl_complete_word.html b/libtecla-1.6.1/html/cpl_complete_word.html deleted file mode 100644 index 0c976c0..0000000 --- a/libtecla-1.6.1/html/cpl_complete_word.html +++ /dev/null @@ -1,382 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="cpl_complete_word.html"><b>cpl_complete_word</b></a> <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a> - - - -</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_recall_matches, - 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); - - CplMatches *cpl_recall_matches(WordCompletion *cpl); - - 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); - - - #define CPL_CHECK_FN(fn) int (fn)(void *data, \ - const char *pathname) - - typedef CPL_CHECK_FN(CplCheckFn); - - CPL_CHECK_FN(cpl_check_exe); - - CplFileConf *new_CplFileConf(void); - - CplFileConf *del_CplFileConf(CplFileConf *cfc); - - void cfc_literal_escapes(CplFileConf *cfc, int literal); - - void cfc_file_start(CplFileConf *cfc, int start_index); - - void cfc_set_check_fn(CplFileConf *cfc, CplCheckFn *chk_fn, - void *chk_data); - - - -</pre><h2>DESCRIPTION</h2><pre> - The cpl_complete_word() function is part of the tecla library (see the - <a href="libtecla.html"><b>libtecla</b></a> man page). It is usually called behind the - scenes by <a href="gl_get_line.html"><b>gl_get_line</b></a>, but can also be called sepa- - rately. - - Given an input line containing an incomplete word to be completed, it - calls a user-provided callback function (or the provided file-comple- - tion 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 cpl_add_comple- - tion(). - - - Descriptions of the functions of this module are as follows: - - WordCompletion *new_WordCompletion(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(). - - WordCompletion *del_WordCompletion(WordCompletion *cpl) - - This function deletes the resources that were returned by a previous - call to new_WordCompletion(). 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 func- - tion. In particular, the line argument contains the input line contain- - ing the word to be completed, and word_end is the index of the charac- - ter 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 com- - pletion function looks backwards until it hits an unescaped space, or - the start of the line. Having found the start of the word, the call- - back 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 call- - ing cpl_record_error(). - - void cpl_record_error(WordCompletion *cpl, - const char *errmsg); - - The last error message recorded by calling cpl_record_error(), can sub- - sequently 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 - 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 cpl_add_completion() returns. - - Note that in the array of possible completions which the cpl_com- - plete_word() function returns, the suffix recorded by cpl_add_comple- - tion() 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 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 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_com- - plete_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 completion. This is some- - thing 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 separa- - tor 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"><b>gl_get_line</b></a>, but can also be called separately if you - separately allocate a WordCompletion object. It performs word comple- - tion, as described at the beginning of this section. Its first argument - is a resource object previously returned by new_WordCompletion(). The - line argument is the input line string, containing the word to be com- - pleted. 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 function. - - If no errors occur, the cpl_complete_word() function returns a pointer - to a CplMatches container, as defined below. This container is allo- - cated 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_com- - pletion(). - - CplMatches *cpl_recall_matches(WordCompletion *cpl); - - As a convenience, the return value of the last call to cpl_com- - plete_word() can be recalled at a later time by calling - cpl_recall_matches(). If cpl_complete_word() returned NULL, so will - cpl_recall_matches(). - - int cpl_list_completions(CplMatches *result, FILE *fp, - int terminal_width); - - When the cpl_complete_word() function returns multiple possible comple- - tions, 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"><b>gl_get_line</b></a> function, passes the follow- - ing completion callback function to cpl_complete_word(). This function - can also be used separately, either by sending it to cpl_com- - plete_word(), or by calling it directly from your own completion call- - back 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. Otherwise it should be a pointer to a CplFile- - Conf object, previously 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 back- - wards 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 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 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. - - #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 file- - name that it is given represents a normal file that the user has exe- - cute permission to. You could use this to have cpl_file_completions() - only list completions 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 completion in ~username/ expressions, in cpl_file_comple- - tions(). - - Using the libtecla_r.a 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 WordCompletion 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"><b>libtecla</b></a>, <a href="gl_get_line.html"><b>gl_get_line</b></a>, <a href="ef_expand_file.html"><b>ef_expand_file</b></a>, - <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/ef_expand_file.html b/libtecla-1.6.1/html/ef_expand_file.html deleted file mode 100644 index c780cf6..0000000 --- a/libtecla-1.6.1/html/ef_expand_file.html +++ /dev/null @@ -1,213 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="ef_expand_file.html"><b>ef_expand_file</b></a> <a href="ef_expand_file.html"><b>ef_expand_file</b></a> - - - -</pre><h2>NAME</h2><pre> - ef_expand_file, del_ExpandFile, ef_last_error, ef_list_expansions, - new_ExpandFile - expand filenames containing ~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"><b>libtecla</b></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. Other- - wise, 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() func- - tion. 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 num- - ber 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 docu- - mented at the start of this section. Its first argument 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 wildcards, then the contained files[] array will contain - the names of the nfile existing files that matched the wildcarded file- - name, 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 (Expand- - File *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 com- - mand, 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 speci- - fied 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 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, provided that each - thread uses a separately allocated ExpandFile object. In other words, - if two threads want to do file expansion, they should each call - new_ExpandFile() to allocate 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"><b>libtecla</b></a>, <a href="gl_get_line.html"><b>gl_get_line</b></a>, <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a>, - <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="ef_expand_file.html"><b>ef_expand_file</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/enhance.html b/libtecla-1.6.1/html/enhance.html deleted file mode 100644 index 62b4e2f..0000000 --- a/libtecla-1.6.1/html/enhance.html +++ /dev/null @@ -1,75 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="enhance.html"><b>enhance</b></a> <a href="enhance.html"><b>enhance</b></a> - - - -</pre><h2>NAME</h2><pre> - enhance - A program that adds command-line editing to third party pro- - grams. - -</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 terminal. It uses the tecla command-line edit- - ing 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. - - 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 impercep- - tible to the user, isn't necessary for correct operation of the pro- - gram. It is just an optimization, designed to stop the input line from - being redisplayed so often that it slows down output. - - Note that the user-level command-line editing facilities provided by - the Tecla library are documented in the <a href="tecla.html"><b>tecla</b></a> man page - - -</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 con- - trolling 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 knowing - that this has happened, and continues to echo typed input to its con- - trolling 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 pro- - gram that switches to noecho mode explicitly restores echoing after- - wards, 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. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library. - ~/.teclarc - The tecla personal customization file. - - -</pre><h2>SEE ALSO</h2><pre> - <a href="tecla.html"><b>tecla</b></a>, <a href="libtecla.html"><b>libtecla</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="enhance.html"><b>enhance</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/gl_get_line.html b/libtecla-1.6.1/html/gl_get_line.html deleted file mode 100644 index 3df39d6..0000000 --- a/libtecla-1.6.1/html/gl_get_line.html +++ /dev/null @@ -1,1996 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="gl_get_line.html"><b>gl_get_line</b></a> <a href="gl_get_line.html"><b>gl_get_line</b></a> - - - -</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_his- - tory, gl_group_history, gl_show_history, gl_watch_fd, gl_inactiv- - ity_timeout, gl_terminal_size, gl_set_term_size, gl_resize_history, - gl_limit_history, gl_clear_history, gl_toggle_history, gl_lookup_his- - tory, 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, gl_completion_action, gl_display_text, - gl_return_status, gl_error_message, gl_catch_blocked, gl_list_signals, - gl_bind_keyseq, gl_erase_terminal, gl_automatic_history, gl_append_his- - tory, gl_query_char, gl_read_char - 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_query_char(GetLine *gl, const char *prompt, - char defchar); - - int gl_read_char(GetLine *gl); - - 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_bind_keyseq(GetLine *gl, GlKeyOrigin origin, - const char *keyseq, const char *action); - - 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_inactivity_timeout(GetLine *gl, GlTimeoutFn *callback, - void *data, unsigned long sec, - unsigned long nsec); - - 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_set_term_size(GetLine *gl, int ncolumn, int 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(GetLine *gl); - - int gl_completion_action(GetLine *gl, - void *data, CplMatchFn *match_fn, - int list_only, const char *name, - const char *keyseq); - - int gl_register_action(GetLine *gl, void *data, - GlActionFn *fn, const char *name, - const char *keyseq); - - int gl_display_text(GetLine *gl, int indentation, - const char *prefix, - const char *suffix, int fill_char, - int def_width, int start, - const char *string); - - GlReturnStatus gl_return_status(GetLine *gl); - - const char *gl_error_message(GetLine *gl, char *buff, - size_t n); - - void gl_catch_blocked(GetLine *gl); - - int gl_list_signals(GetLine *gl, sigset_t *set); - - int gl_append_history(GetLine *gl, const char *line); - - int gl_automatic_history(GetLine *gl, int enable); - - - -</pre><h2>DESCRIPTION</h2><pre> - The gl_get_line() function is part of the tecla library (see the libte- - cla(@LIBR_MANEXT@) man page). If the user is typing at a terminal, each - call prompts them for an line of input, then provides interactive edit- - ing 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. Documentation of both the user-level command- - line editing features and all user configuration options, can be found - in the <a href="tecla.html"><b>tecla</b></a> man page. This man page concerns itself - with documentation for programmers interested in using this library in - their application. - - -</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() func- - tion 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 allocated by new_Get- - Line(), are returned to the system by calling 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 num- - ber 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, specifying 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 posi- - tioned 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. Note that the line pointer returned by one - call to gl_get_line() can be passed back to the next call to - gl_get_line() via the start_line. This allows the application to take - the last entered line, and if it contains an error, to then present it - back to the user for re-editing, with the cursor initially positioned - where the error was encountered. - - 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 termi- - nal,gl_get_line() just calls fgets(). - - -</pre><h2>THE RETURN STATUS OF GL_GET_LINE</h2><pre> - As described above, the gl_get_line() function has two possible return - values; a pointer to the completed input line, or NULL. Extra informa- - tion about what caused gl_get_line() to return is available both by - inspecting errno, and by calling the gl_return_status() function. - - - GlReturnStatus gl_return_status(GetLine *gl); - - - The following are the possible enumerated values that this function - returns. - - - GLR_NEWLINE - The last call to gl_get_line() - successfully returned a completed - input line. - - GLR_BLOCKED - gl_get_line() was in non-blocking - server mode, and returned early to - avoid blocking the process while - waiting for terminal I/O. The - gl_pending_io() function can be - used to see what type of I/O - gl_get_line() was waiting for. - (see the <a href="gl_io_mode.html"><b>gl_io_mode</b></a> man page - for details). - - GLR_SIGNAL - A signal was caught by - gl_get_line() that had an - after-signal disposition of - GLS_ABORT (See gl_trap_signal()). - - GLR_TIMEOUT - The inactivity timer expired while - gl_get_line() was waiting for - input, and the timeout callback - function returned GLTO_ABORT. - See gl_inactivity_timeout() for - information about timeouts. - - GLR_FDABORT - An application I/O callack returned - GLFD_ABORT (see gl_watch_fd()). - - GLR_EOF - End of file reached. This can happen - when input is coming from a file or a - pipe, instead of the terminal. It also - occurs if the user invokes the - list-or-eof or del-char-or-list-or-eof - actions at the start of a new line. - - GLR_ERROR - An unexpected error caused - gl_get_line() to abort (consult - errno and/or - gl_error_message() for details. - - - When gl_return_status() returns GLR_ERROR, and the value of errno isn't - sufficient to explain what happened, you can use the gl_error_message() - function to request a description of the last error that occurred. - - - const char *gl_error_message(GetLine *gl, char *buff, - size_t n); - - - The return value is a pointer to the message that occurred. If the buff - argument is NULL, this will be a pointer to a buffer within gl, who's - value will probably change on the next call to any function associated - with gl_get_line(). Otherwise, if a non-NULL buff argument is provided, - the error message, including a '\0' terminator, will be written within - the first n elements of this buffer, and the return value will be a - pointer to the first element of this buffer. If the message won't fit - in the provided buffer, it will be truncated to fit. - - -</pre><h2>OPTIONAL PROMPT FORMATTING</h2><pre> - Whereas by default the prompt string that you specify is displayed lit- - erally, without any special interpretation of the characters within it, - the gl_prompt_style() function can be used to enable optional format- - ting 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>ALTERNATE CONFIGURATION SOURCES</h2><pre> - As mentioned above, by default users have the option of configuring 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 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 informa- - tion 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 config- - uration 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 characters. If app_file != NULL then it is - interpreted as the full pathname of an application-specific configura- - tion file. If user_file != NULL then it is interpreted as the full - pathname 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 configura- - tion commands from an optional .teclarc file in the user's home direc- - tory. Note that the arguments are listed in ascending order of prior- - ity, with the contents of app_string being potentially overriden by - commands in app_file, and commands in app_file potentially being over- - riden 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 specifies the - filenames that you want re-read when the user requests that the config- - uration files be re-read. - - Individual key sequences can also be bound and unbound using the - gl_bind_keyseq() function. - - - int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, - const char *keyseq, - const char *action); - - - The origin argument specifies the priority of the binding, according to - who it is being established for, and must be one of the following two - values. - - GL_USER_KEY - The user requested this key-binding. - GL_APP_KEY - This is a default binding set by the - application. - - When both user and application bindings for a given key-sequence have - been specified, the user binding takes precedence. The application's - binding is subsequently reinstated if the user's binding is later - unbound via either another to this function, or a call to gl_config- - ure_getline(). - - The keyseq argument specifies the key-sequence to be bound or unbound, - and is expressed in the same way as in a ~/.teclarc configuration file. - The action argument must either be a string containing the name of the - action to bind the key-sequence to, or it must be NULL or "" to unbind - the key-sequence. - - -</pre><h2>CUSTOMIZED WORD COMPLETION</h2><pre> - 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 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 arbi- - trary, 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 call- - back functions. The declaration and responsibilities of callback func- - tions are described in depth in the <a href="cpl_complete_word.html"><b>cpl_complete_word</b></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 possi- - ble completions of this word, and record them one by one in the Word- - Completion object that is passed to it as an argument, by calling the - cpl_add_completion() function. If the callback function wishes to pro- - vide 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 cpl_com- - plete_word(@FUNC_MANEXT@) 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 character, then gl_get_line() will - return this input line. - - - If, for some reason, your callback function needs to write something to - the terminal, it must call gl_normal_io() before doing so. This will - start a new line after the input line that is currently being edited, - reinstate normal terminal I/O, and tell gl_get_line() that the input - line will need to be redrawn when the callback returns. - - -</pre><h2>ADDING COMPLETION ACTIONS</h2><pre> - In the previous section the ability to customize the behavior of the - only default completion action, complete-word, was described. In this - section the ability to install additional action functions, so that - different types of word completion can be bound to different key- - sequences, is described. This is achieved by using the gl_comple- - tion_action() function. - - - int gl_completion_action(GetLine *gl, - void *data, CplMatchFn *match_fn, - int list_only, const char *name, - const char *keyseq); - - - The data and match_fn arguments are as described in the cpl_com- - plete_word man page, and specify the callback function that should be - invoked to identify possible completions. The list_only argument - determines whether the action that is being defined should attempt to - complete the word as far as possible in the input line before display- - ing any possible ambiguous completions, or whether it should simply - display the list of possible completions without touching the input - line. The former option is selected by specifying a value of 0, and the - latter by specifying a value of 1. The name argument specifies the name - by which configuration files and future invokations of this function - should refer to the action. This must either be the name of an existing - completion action to be changed, or be a new unused name for a new - action. Finally, the keyseq argument specifies the default key-sequence - to bind the action to. If this is NULL, no new keysequence will be - bound to the action. - - Beware that in order for the user to be able to change the key-sequence - that is bound to actions that are installed in this manner, when you - call gl_completion_action() to install a given action for the first - time, you should do this between calling new_GetLine() and the first - call to gl_get_line(). Otherwise, when the user's configuration file - is read on the first call to gl_get_line(), the name of the your addi- - tional action won't be known, and any reference to it in the configura- - tion file will generate an error. - - As discussed for gl_customize_completion(), if your callback function, - for some reason, needs to write anything to the terminal, it must call - gl_normal_io() before doing so. - - -</pre><h2>DEFINING CUSTOM ACTIONS</h2><pre> - Although the built-in key-binding actions are sufficient for the needs - of most applications, occasionally a specialized application may need - to define one or more custom actions, bound to application-specific - key-sequences. For example, a sales application would benefit from hav- - ing a key-sequence that displayed the part name that corresponded to a - part number preceding the cursor. Such a feature is clearly beyond the - scope of the built-in action functions. So for such special cases, the - gl_register_action() function is provided. - - - int gl_register_action(GetLine *gl, void *data, - GlActionFn *fn, const char *name, - const char *keyseq); - - - This function lets the application register an external function, fn, - that will thereafter be called whenever either the specified key- - sequence, keyseq, is entered by the user, or the user enters any other - key-sequence that the user subsequently binds to the specified action - name, name, in their configuration file. The data argument can be a - pointer to anything that the application wishes to have passed to the - action function, fn, whenever that function is invoked. - - The action function, fn, should be declared using the following macro, - which is defined in libtecla.h. - - - #define GL_ACTION_FN(fn) GlAfterAction (fn)(GetLine *gl, \ - void *data, int count, size_t curpos, \ - const char *line) - - - The gl and data arguments are those that were previously passed to - gl_register_action() when the action function was registered. The count - argument is a numeric argument which the user has the option of enter- - ing using the digit-argument action, before invoking the action. If the - user doesn't enter a number, then the count argument is set to 1. Nomi- - nally this argument is interpreted as a repeat count, meaning that the - action should be repeated that many times. In practice however, for - some actions a repeat count makes little sense. In such cases, actions - can either simply ignore the count argument, or use its value for a - different purpose. - - A copy of the current input line is passed in the read-only line argu- - ment. The current cursor position within this string is given by the - index contained in the curpos argument. Note that direct manipulation - of the input line and the cursor position is not permitted. This is - because the rules dicated by various modes, such as vi mode versus - emacs mode, no-echo mode, and insert mode versus overstrike mode etc, - make it too complex for an application writer to write a conforming - editing action, as well as constrain future changes to the internals of - gl_get_line(). A potential solution to this dilema would be to allow - the action function to edit the line using the existing editing - actions. This is currently under consideration. - - If the action function wishes to write text to the terminal, without - this getting mixed up with the displayed text of the input line, or - read from the terminal without having to handle raw terminal I/O, then - before doing either of these operations, it must temporarily suspend - line editing by calling the gl_normal_io() function. This function - flushes any pending output to the terminal, moves the cursor to the - start of the line that follows the last terminal line of the input - line, then restores the terminal to a state that is suitable for use - with the C stdio facilities. The latter includes such things as restor- - ing the normal mapping of \n to \r\n, and, when in server mode, restor- - ing the normal blocking form of terminal I/O. Having called this func- - tion, the action function can read from and write to the terminal with- - out the fear of creating a mess. It isn't necessary for the action - function to restore the original editing environment before it returns. - This is done automatically by gl_get_line() after the action function - returns. The following is a simple example of an action function which - writes the sentence "Hello world" on a new terminal line after the line - being edited. When this function returns, the input line is redrawn on - the line that follows the "Hello world" line, and line editing resumes. - - - static GL_ACTION_FN(say_hello_fn) - { - if(gl_normal_io(gl)) /* Temporarily suspend editing */ - return GLA_ABORT; - printf("Hello world\n"); - return GLA_CONTINUE; - } - - - Action functions must return one of the following values, to tell - gl_get_line() how to procede. - - - GLA_ABORT - Cause gl_get_line() to return NULL. - GLA_RETURN - Cause gl_get_line() to return the - completed input line. - GLA_CONTINUE - Resume command-line editing. - - - Note that the name argument of gl_register_action() specifies the name - by which a user can refer to the action in their configuration file. - This allows them to re-bind the action to an alternate key-seqeunce. In - order for this to work, it is necessary to call gl_register_action() - between calling new_GetLine() and the first call to gl_get_line(). - - -</pre><h2>HISTORY FILES</h2><pre> - To save the contents of the history buffer before quitting your appli- - cation, and subsequently restore them when you next start the applica- - tion, the following functions are provided. - - - 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 environment 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 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 pre- - fixes differ in different languages, the comment 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 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 his- - tory 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-exis- - tence of a file to be an error. - - -</pre><h2>MULTIPLE HISTORY LISTS</h2><pre> - If your application uses a single GetLine object for entering many dif- - ferent 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. Initially this identi- - fier 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 identifiers and historical input lines between pro- - gram invokations, so you should choose fixed identifiers for the dif- - ferent types of input line used by your application. - - Whenever gl_get_line() 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. - - -</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 his- - tory 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 char- - acters which are written verbatim, interleaved with any of the follow- - ing 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 application 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 succes- - sively higher numbers. Note that the range of lines currently preserved - in the history 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 function that takes gl as its argument. There- - fore you should make a private copy of this string if you need to keep - it around. - - -</pre><h2>MANUAL HISTORY ARCHIVAL</h2><pre> - By default, whenever a line is entered by the user, it is automatically - appended to the history list, just before gl_get_line() returns the - line to the caller. This is convenient for the majority of applica- - tions, but there are also applications that need finer grained control - over what gets added to the history list. In such cases, the automatic - addition of entered lines to the history list can be turned off by - calling the gl_automatic_history() function. - - - int gl_automatic_history(GetLine *gl, int enable); - - - If this function is called with its enable argument set to 0, - gl_get_line() won't automatically archive subsequently entered lines. - Automatic archiving can be reenabled at a later time, by calling this - function again, with its enable argument set to 1. While automatic - history archiving is disabled, the calling application can use the - gl_append_history() to append lines to the history list as needed. - - - int gl_append_history(GetLine *gl, const char *line); - - - The line argument specifies the line to be added to the history list. - This must be a normal ' ' terminated string. If this string contains - any newline characters, the line that gets archived in the history list - will be terminated by the first of these. Otherwise it will be termi- - nated by the ' ' terminator. If the line is longer than the maximum - input line length, that was specified when new_GetLine() was called, - when the line is recalled, it will get truncated to the actual - gl_get_line() line length. - - If successful, gl_append_history() returns 0. Otherwise it returns non- - zero, and sets errno to one of the following values. - - - EINVAL - One of the arguments passed to - gl_append_history() was NULL. - ENOMEM - The specified line was longer than the allocated - size of the history buffer (as specified when - new_GetLine() was called), so it couldn't be - archived. - - - A textual description of the error can optionally be obtained by call- - ing gl_error_message(). Note that after such an error, the history list - remains in a valid state to receive new history lines, so there is lit- - tle harm in simply ignoring the return status of gl_append_history(). - - -</pre><h2>MISCELLANEOUS HISTORY CONFIGURATION</h2><pre> - If you wish to change the size of the history buffer that was origi- - nally 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 spec- - ify 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 discarded. - - 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_his- - tory()), or all historical lines in the buffer. - - The gl_toggle_history() function allows you to toggle history 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 history is turned off, no new - lines will be added to the history list, and history lookup key-bind- - ings 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 variable 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 written 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 - database (terminfo or termcap), in order to determine which special - control sequences are needed to control various aspects of the termi- - nal. 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 terminal 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> - By default, gl_get_line() doesn't return until either a complete input - line has been entered by the user, or an error occurs. In programs that - need to watch for I/O from other sources than the terminal, there are - two options. - - - 1. Use the functions described in the - <a href="gl_io_mode.html"><b>gl_io_mode</b></a> man page to switch - gl_get_line() into non-blocking server mode. In this mode, - gl_get_line() becomes a non-blocking, incremental - line-editing function that can safely be called from - an external event loop. Although this is a very - versatile method, it involves taking on some - responsibilities that are normally performed behind - the scenes by gl_get_line(). - - 2. 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 argu- - ment 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 call- - back function for its own use, and can point to anything 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 - function should be one of the following values. - - - GLFD_ABORT - Tell gl_get_line() to abort. When this - happens, gl_get_line() returns - NULL, and a following call to - gl_return_status() will return - GLR_FDABORT. Note that if the - application needs errno always to - have a meaningful value when - gl_get_line() returns NULL, - the callback function should set - errno appropriately. - 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 sig- - nals, 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. - - - - If the callback function needs to read or write to the terminal, it - should ideally first call gl_normal_io(gl) to temporarily suspend line - editing. This will restore the terminal to canonical, blocking-I/O, - mode, and move the cursor to the start of a new terminal line. Later, - when the callback returns, gl_get_line() will notice that gl_nor- - mal_io() was called, redisplay the input line and resume editing. Note - that in this case the return values, GLFD_REFRESH and GLFD_CONTINUE are - equivalent. - - - - To support cases where the callback function calls a third-party func- - tion which occasionally and u0prisicre-enabledesbeforee themicallback - automatic conversion of "0 to " - function is called. If the callack knows that the third-party function - wrote to the terminal, it should then return the GLFD_REFRESH return - value, to tell gl_get_line() to redisplay the input line. - - - - 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 arguments, but with a callback argument - of 0. The data argument is ignored in this case. - - -</pre><h2>SETTING AN INACTIVITY TIMEOUT</h2><pre> - On systems with the select() system call, the gl_inactivity_timeout() - function can be used to set or cancel an inactivity timeout. Inactivity - in this case refers both to keyboard input, and to I/O on any file - descriptors registered by prior and subsequent calls to gl_watch_fd(). - On oddball systems that don't have select(), this call has no effect. - - - int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *callback, - void *data, unsigned long sec, - unsigned long nsec); - - - The timeout is specified in the form of an integral number of seconds - and an integral number of nanoseconds, via the sec and nsec arguments - respectively. Subsequently, whenever no activity is seen for this time - period, the function specified via the callback argument is called. The - data argument of gl_inactivity_timeout() is passed verbatim to this - callback function whenever it is invoked, and can thus be used to pass - arbitrary application-specific information to the callback. The follow- - ing macro is provided in libtecla.h for applications to use to declare - and prototype timeout callback functions. - - - #define GL_TIMEOUT_FN(fn) \ - GlAfterTimeout (fn)(GetLine *gl, void *data) - - - On returning, the application's callback is expected to return one of - the following enumerators to tell gl_get_line() how to procede after - the timeout has been handled by the callback. - - - GLTO_ABORT - Tell gl_get_line() to abort. When - this happens, gl_get_line() will - return NULL, and a following call - to gl_return_status() will return - GLR_TIMEOUT. Note that if the - application needs errno always to - have a meaningful value when - gl_get_line() returns NULL, - the callback function should set - errno appropriately. - GLTO_REFRESH - Redraw the input line, then continue - waiting for input. You should return - this value if your callback wrote to the - terminal without having first called - gl_normal_io(gl). - GLTO_CONTINUE - In normal blocking-I/O mode, continue to - wait for input, without redrawing the - user's input line. - In non-blocking server I/O mode (see - <a href="gl_io_mode.html"><b>gl_io_mode</b></a>), cause gl_get_line() - to act as though I/O blocked. This means - that gl_get_line() will immediately - return NULL, and a following call - to gl_return_status() will return - GLR_BLOCKED. - - - Note that before calling the callback, gl_get_line() blocks most sig- - nals, 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. - - - - If the callback function needs to read or write to the terminal, it - should ideally first call gl_normal_io(gl) to temporarily suspend line - editing. This will restore the terminal to canonical, blocking-I/O, - mode, and move the cursor to the start of a new terminal line. Later, - when the callback returns, gl_get_line() will notice that gl_nor- - mal_io() was called, redisplay the input line and resume editing. Note - that in this case the return values, GLTO_REFRESH and GLTO_CONTINUE are - equivalent. - - - - To support cases where the callback function calls a third-party func- - tion which occasionally and u0prisicre-enabledesbeforee themicallback - automatic conversion of "0 to " - function is called. If the callack knows that the third-party function - wrote to the terminal, it should then return the GLTO_REFRESH return - value, to tell gl_get_line() to redisplay the input line. - - - - Note that although the timeout argument includes a nano-second compo- - nent, few computer clocks presently have resolutions that are finer - than a few milliseconds, so asking for less than a few milliseconds is - equivalent to requesting zero seconds on a lot of systems. If this - would be a problem, you should base your timeout selection on the - actual resolution of the host clock (eg. by calling - sysconf(_SC_CLK_TCK)). - - - - To turn off timeouts, simply call gl_inactivity_timeout() with a call- - back 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 ter- - minate 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 sec- - tion. - - When the following subset of signals are caught, gl_get_line() first - restores the terminal settings and signal handling to how they were - before gl_get_line() was called, resends the signal, to allow the call- - ing application's signal handlers to handle it, then if the process - 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 following function. - - int gl_last_signal(const GetLine *gl); - - This returns the numeric code (eg. SIGINT) of the last signal that was - received during the most recent call to gl_get_line(), or -1 if no sig- - nals 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 keyboard 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. - - SIGPOLL - On SVR4 systems, this signal notifies the - process of an asynchronous I/O event. Note - that under 4.3+BSD, SIGIO and SIGPOLL are - the same. On other systems, SIGIO is ignored - by default, so gl_get_line() doesn't - trap it by default. - - 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. - - SIGXFSZ - This signal is generated when a process - exceeds its soft file-size 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 or SIGPOLL, 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-con- - trol shells usually reset the terminal settings when a process relin- - quishes the controlling 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 sig- - nal 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 envi- - ronment 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 overridden it, never either writes to the termi- - nal, nor suspends or terminates the calling 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 argu- - ment 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 sig- - nal 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. 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 GL_SUSPEND_INPUT - combination is better if you know that you are always going to be writ- - ting 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 abort. When - this happens, gl_get_line() returns - NULL, and a following call to - gl_return_status() will return - GLR_SIGNAL. Note that if the - application needs errno always to - have a meaningful value when - gl_get_line() returns NULL, - the callback function should set - errno appropriately. - 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 calling program. It can also, however, - be used with the GL_RETURN 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. - - -</pre><h2>RELIABLE SIGNAL HANDLING</h2><pre> - Signal handling is suprisingly hard to do reliably without race condi- - tions. In gl_get_line() a lot of care has been taken to allow applica- - tions to perform reliable signal handling around gl_get_line(). This - section explains how to make use of this. - - As an example of the problems that can arise if the application isn't - written correctly, imagine that one's application has a SIGINT signal - handler that sets a global flag. Now suppose that the application tests - this flag just before invoking gl_get_line(). If a SIGINT signal hap- - pens to be received in the small window of time between the statement - that tests the value of this flag, and the statement that calls - gl_get_line(), then gl_get_line() will not see the signal, and will not - be interrupted. As a result, the application won't be able to respond - to the signal until the user gets around to finishing entering the - input line and gl_get_line() returns. Depending on the application, - this might or might not be a disaster, but at the very least it would - puzzle the user. - - The way to avoid such problems is to do the following. - - 1. If needed, use the gl_trap_signal() function to - configure gl_get_line() to abort when important - signals are caught. - - 2. Configure gl_get_line() such that if any of the - signals that it catches are blocked when - gl_get_line() is called, they will be unblocked - automatically during times when gl_get_line() is - waiting for I/O. This can be done either - on a per signal basis, by calling the - gl_trap_signal() function, and specifying the - GLS_UNBLOCK attribute of the signal, or globally by - calling the gl_catch_blocked() function. - - - void gl_catch_blocked(GetLine *gl); - - - This function simply adds the GLS_UNBLOCK attribute - to all of the signals that it is currently configured to - trap. - - 3. Just before calling gl_get_line(), block delivery - of all of the signals that gl_get_line() is - configured to trap. This can be done using the POSIX - sigprocmask() function in conjunction with the - gl_list_signals() function. - - - int gl_list_signals(GetLine *gl, sigset_t *set); - - - This function returns the set of signals that it is - currently configured to catch in the set argument, - which is in the form required by sigprocmask(). - - 4. In the example, one would now test the global flag that - the signal handler sets, knowing that there is now no - danger of this flag being set again until - gl_get_line() unblocks its signals while performing - I/O. - - 5. Eventually gl_get_line() returns, either because - a signal was caught, an error occurred, or the user - finished entering their input line. - - 6. Now one would check the global signal flag again, and if - it is set, respond to it, and zero the flag. - - 7. Use sigprocmask() to unblock the signals that were - blocked in step 3. - - The same technique can be used around certain POSIX signal-aware func- - tions, such as sigsetjmp() and sigsuspend(), and in particular, the - former of these two functions can be used in conjunction with sig- - longjmp() to implement race-condition free signal handling around other - long-running system calls. The way to do this, is explained next, by - showing how gl_get_line() manages to reliably trap signals around calls - to functions like read() and select() without race conditions. - - The first thing that gl_get_line() does, whenever it is called, is to - use the POSIX sigprocmask() function to block the delivery of all of - the signals that it is currently configured to catch. This is redundant - if the application has already blocked them, but it does no harm. It - undoes this step just before returning. - - Whenever gl_get_line() needs to call read() or select() to wait for - input from the user, it first calls the POSIX sigsetjmp() function, - being sure to specify a non-zero value for its savesigs argument. The - reason for the latter argument will become clear shortly. - - If sigsetjmp() returns zero, gl_get_line() then does the following. - - - a. It uses the POSIX sigaction() function to register - a temporary signal handler to all of the signals that it - is configured to catch. This signal handler does two - things. - - 1. It records the number of the signal that was received - in a file-scope variable. - - 2. It then calls the POSIX siglongjmp() - function using the buffer that was passed to - sigsetjmp() for its first argument, and - a non-zero value for its second argument. - - When this signal handler is registered, the sa_mask - member of the struct sigaction act argument of the - call to sigaction() is configured to contain all of - the signals that gl_get_line() is catching. This - ensures that only one signal will be caught at once by - our signal handler, which in turn ensures that multiple - instances of our signal handler don't tread on each - other's toes. - - b. Now that the signal handler has been set up, - gl_get_line() unblocks all of the signals that it - is configured to catch. - - c. It then calls the read() or select() system - calls to wait for keyboard input. - - d. If this system call returns (ie. no signal is received), - gl_get_line() blocks delivery of the signals of - interest again. - - e. It then reinstates the signal handlers that were - displaced by the one that was just installed. - - - Alternatively, if sigsetjmp() returns non-zero, this means that one of - the signals being trapped was caught while the above steps were execut- - ing. When this happens, gl_get_line() does the following. - - First, note that when a call to siglongjmp() causes sigsetjmp() to - return, provided that the savesigs argument of sigsetjmp() was non- - zero, as specified above, the signal process mask is restored to how it - was when sigsetjmp() was called. This is the important difference - between sigsetjmp() and the older problematic setjmp(), and is the - essential ingredient that makes it possible to avoid signal handling - race conditions. Because of this we are guaranteed that all of the - signals that we blocked before calling sigsetjmp() are blocked again as - soon as any signal is caught. The following statements, which are then - executed, are thus guaranteed to be executed without any further sig- - nals being caught. - - 1. If so instructed by the gl_get_line() configuration - attributes of the signal that was caught, - gl_get_line() restores the terminal attributes to - the state that they had when gl_get_line() was - called. This is particularly important for signals that - suspend or terminate the process, since otherwise the - terminal would be left in an unusable state. - - 2. It then reinstates the application's signal handlers. - - 3. Then it uses the C standard-library raise() - function to re-send the application the signal that - was caught. - - 3. Next it unblocks delivery of the signal that we just - sent. This results in the signal that was just sent - via raise(), being caught by the application's - original signal handler, which can now handle it as it - sees fit. - - 4. If the signal handler returns (ie. it doesn't terminate - the process), gl_get_line() blocks delivery of the - above signal again. - - 5. It then undoes any actions performed in the first of the - above steps, and redisplays the line, if the signal - configuration calls for this. - - 6. gl_get_line() then either resumes trying to - read a character, or aborts, depending on the - configuration of the signal that was caught. - - What the above steps do in essence is to take asynchronously delivered - signals and handle them synchronously, one at a time, at a point in the - code where gl_get_line() has complete control over its environment. - - -</pre><h2>THE TERMINAL SIZE</h2><pre> - On most systems the combination of the TIOCGWINSZ ioctl and the SIG- - WINCH 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 vari- - ables. 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. - - Even on systems that do support ioctl(TIOCGWINSZ), if the terminal is - on the other end of a serial line, the terminal driver generally has no - way of detecting when a resize occurs or of querying what the current - size is. In such cases no SIGWINCH is sent to the process, and the - dimensions returned by ioctl(TIOCGWINSZ) aren't correct. The only way - to handle such instances is to provide a way for the user to enter a - command that tells the remote system what the new size is. This command - would then call the gl_set_term_size() function to tell gl_get_line() - about the change in size. - - - int gl_set_term_size(GetLine *gl, int ncolumn, int nline); - - - The ncolumn and nline arguments are used to specify the new dimensions - of the terminal, and must not be less than 1. On systems that do sup- - port ioctl(TIOCGWINSZ), this function first calls ioctl(TIOCSWINSZ) to - tell the terminal driver about the change in size. In non-blocking - server-I/O mode, if a line is currently being input, the input line is - then redrawn to accomodate the changed size. Finally the new values are - recorded in gl for future use by gl_get_line(). - - The gl_terminal_size() 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. - - 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 fallback terminal dimen- - sions, 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 via - ioctl(TIOCGWINSZ) or environment variables. - - -</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. Fur- - thermore, 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 tog- - gle on and off the display and archival of any text that is subse- - quently 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 - provided that history hasn't been turned off via a call to gl_tog- - gle_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 set- - ting via the return value. In all cases, the return value of the func- - tion 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 completion will - invisibly complete your prefix as far as possible, ambiguous comple- - tions will not be displayed. - - -</pre><h2>SINGLE CHARACTER QUERIES</h2><pre> - Using gl_get_line() to query the user for a single character reply, is - inconvenient for the user, since they must hit the enter or return key - before the character that they typed is returned to the program. Thus - the gl_query_char() function has been provided for single character - queries like this. - - - int gl_query_char(GetLine *gl, const char *prompt, - char defchar); - - - This function displays the specified prompt at the start of a new line, - and waits for the user to type a character. When the user types a char- - acter, gl_query_char() displays it to the right of the prompt, starts a - newline, then returns the character to the calling program. The return - value of the function is the character that was typed. If the read had - to be aborted for some reason, EOF is returned instead. In the latter - case, the application can call the previously documented gl_return_sta- - tus(), to find out what went wrong. This could, for example, have been - the reception of a signal, or the optional inactivity timer going off. - - If the user simply hits enter, the value of the defchar argument is - substituted. This means that when the user hits either newline or - return, the character specified in defchar, is displayed after the - prompt, as though the user had typed it, as well as being returned to - the calling application. If such a replacement is not important, simply - pass '0 as the value of defchar. - - If the entered character is an unprintable character, it is displayed - symbolically. For example, control-A is displayed as ^A, and characters - beyond 127 are displayed in octal, preceded by a backslash. - - As with gl_get_line(), echoing of the entered character can be disabled - using the gl_echo_mode() function. - - If the calling process is suspended while waiting for the user to type - their response, the cursor is moved to the line following the prompt - line, then when the process resumes, the prompt is redisplayed, and - gl_query_char() resumes waiting for the user to type a character. - - Note that in non-blocking server mode, (see <a href="gl_io_mode.html"><b>gl_io_mode</b></a>), - if an incomplete input line is in the process of being read when - gl_query_char() is called, the partial input line is discarded, and - erased from the terminal, before the new prompt is displayed. The next - call to gl_get_line() will thus start editing a new line. - - -</pre><h2>READING RAW CHARACTERS</h2><pre> - Whereas the gl_query_char() function visibly prompts the user for a - character, and displays what they typed, the gl_read_char() function - reads a signal character from the user, without writing anything to the - terminal, or perturbing any incompletely entered input line. This means - that it can be called not only from between calls to gl_get_line(), but - also from callback functions that the application has registered to be - called by gl_get_line(). - - - int gl_read_char(GetLine *gl); - - - On success, the return value of gl_read_char() is the character that - was read. On failure, EOF is returned, and the gl_return_status() func- - tion can be called to find out what went wrong. Possibilities include - the optional inactivity timer going off, the receipt of a signal that - is configured to abort gl_get_line(), or terminal I/O blocking, when in - non-blocking server-I/O mode. - - Beware that certain keyboard keys, such as function keys, and cursor - keys, usually generate at least 3 characters each, so a single call to - gl_read_char() won't be enough to identify such keystrokes. - - -</pre><h2>CLEARING THE TERMINAL</h2><pre> - The calling program can clear the terminal by calling gl_erase_termi- - nal(). In non-blocking server-I/O mode, this function also arranges for - the current input line to be redrawn from scratch when gl_get_line() is - next called. - - - int gl_erase_terminal(GetLine *gl); - - - -</pre><h2>DISPLAYING TEXT DYNAMICALLY</h2><pre> - Between calls to gl_get_line(), the gl_display_text() function provides - a convenient way to display paragraphs of text, left-justified and - split over one or more terminal lines according to the constraints of - the current width of the terminal. Examples of the use of this function - may be found in the demo programs, where it is used to display intro- - ductions. In those examples the advanced use of optional prefixes, suf- - fixes and filled lines to draw a box around the text is also illus- - trated. - - - int gl_display_text(GetLine *gl, int indentation, - const char *prefix, - const char *suffix, int fill_char, - int def_width, int start, - const char *string); - - If gl isn't currently connected to a terminal, for example if the out- - put of a program that uses gl_get_line() is being piped to another pro- - gram or redirected to a file, then the value of the def_width parameter - is used as the terminal width. - - The indentation argument specifies the number of characters to use to - indent each line of ouput. The fill_char argument specifies the charac- - ter that will be used to perform this indentation. - - The prefix argument can either be NULL, or be a string to place at the - beginning of each new line (after any indentation). Similarly, the - suffix argument can either be NULL, or be a string to place at the end - of each line. The suffix is placed flush against the right edge of the - terminal, and any space between its first character and the last word - on that line is filled with the character specified via the fill_char - argument. Normally the fill-character is a space. - - The start argument tells gl_display_text() how many characters have - already been written to the current terminal line, and thus tells it - the starting column index of the cursor. Since the return value of - gl_display_text() is the ending column index of the cursor, by passing - the return value of one call to the start argument of the next call, a - paragraph that is broken between more than one string can be composed - by calling gl_display_text() for each successive portion of the para- - graph. Note that literal newline characters are necessary at the end of - each paragraph to force a new line to be started. - - On error, gl_display_text() returns -1. - - -</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. - Except in non-blocking server mode, it has no effect if used between - calls to gl_get_line(). In non-blocking server mode (see the - <a href="gl_io_mode.html"><b>gl_io_mode</b></a> man page, when used between two calls to - gl_get_line() that are operating on the same input line, the current - input line will be re-drawn with the new prompt on the following call - to gl_get_line(). - - - 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 printable in the user's cur- - rent locale are now displayed verbatim and included in the returned - input line. Assuming that the calling program correctly contains a - call like the following, - - 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 variables are defined, or the program - neglects to call setlocale, 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. Further documentation on how the user can make use - of this to enter international characters can be found in the - <a href="tecla.html"><b>tecla</b></a> man page. - - -</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 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 mod- - ule 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. - - -</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"><b>libtecla</b></a>, <a href="gl_io_mode.html"><b>gl_io_mode</b></a>, <a href="tecla.html"><b>tecla</b></a>, <a href="ef_expand_file.html"><b>ef_expand_file</b></a>, - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a>, <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="gl_get_line.html"><b>gl_get_line</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/gl_io_mode.html b/libtecla-1.6.1/html/gl_io_mode.html deleted file mode 100644 index 98c15a7..0000000 --- a/libtecla-1.6.1/html/gl_io_mode.html +++ /dev/null @@ -1,509 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="gl_io_mode.html"><b>gl_io_mode</b></a> <a href="gl_io_mode.html"><b>gl_io_mode</b></a> - - - -</pre><h2>NAME</h2><pre> - gl_io_mode, gl_raw_io, gl_normal_io, gl_tty_signals, gl_abandon_line, - gl_handle_signal, gl_pending_io - How to use gl_get_line() from an - external event loop. - -</pre><h2>SYNOPSIS</h2><pre> - #include <libtecla.h> - - int gl_io_mode(GetLine *gl, GlIOMode mode); - - int gl_raw_io(GetLine *gl); - - int gl_normal_io(GetLine *gl); - - int gl_tty_signals(void (*term_handler)(int), - void (*susp_handler)(int), - void (*cont_handler)(int), - void (*size_handler)(int)); - - void gl_abandon_line(GetLine *gl); - - void gl_handle_signal(int signo, GetLine *gl, int ngl); - - GlPendingIO gl_pending_io(GetLine *gl); - - - -</pre><h2>DESCRIPTION</h2><pre> - The gl_get_line() function, which is documented separately in the - <a href="gl_get_line.html"><b>gl_get_line</b></a> man page, supports two different I/O modes. - These are selected by calling the gl_io_mode() function. - - - int gl_io_mode(GetLine *gl, GlIOMode mode); - - - The mode argument of this function specifies the new I/O mode, and must - be one of the following. - - - GL_NORMAL_MODE - Select the normal blocking-I/O mode. - In this mode gl_get_line() - doesn't return until either an error - occurs of the user finishes entering a - new line. This mode is the focus of - the <a href="gl_get_line.html"><b>gl_get_line</b></a> man page. - - GL_SERVER_MODE - Select non-blocking server I/O mode. - In this mode, since non-blocking - terminal I/O is used, the entry of - each new input line typically requires - many calls to gl_get_line() from - an external I/O-driven event loop. - This mode is the focus of this man - page. - - - Newly created GetLine objects start in normal I/O mode, so to switch to - non-blocking server mode requires an initial call to gl_io_mode(). - - -</pre><h2>SERVER I/O MODE</h2><pre> - In non-blocking server I/O mode, the application is required to have an - event loop which calls gl_get_line() whenever the terminal file - descriptor can do the type I/O that gl_get_line() is waiting for. To - determine which type of I/O gl_get_line() is waiting for, the applica- - tion calls the gl_pending_io() function. - - - GlPendingIO gl_pending_io(GetLine *gl); - - - The return value of this function is one of the following two enumer- - ated values. - - - GLP_READ - gl_get_line() is waiting to write a - character to the terminal. - - GLP_WRITE - gl_get_line() is waiting to read a - character from the keyboad. - - - If the application is using either the select() or poll() system calls - to watch for I/O on a group of file descriptors, then it should call - the gl_pending_io() function before each call to these functions to see - which direction of I/O it should tell them to watch for, and configure - their arguments accordingly. In the case of the select() system call, - this means using the FD_SET() macro to add the terminal file descriptor - either to the set of file descriptors to be watched for readability, or - the set to be watched for writability. - - As in normal I/O mode, the return value of gl_get_line() is either a - pointer to a completed input line, or NULL. However, whereas in normal - I/O mode a NULL return value always means that an error occurred, in - non-blocking server mode, NULL is also returned when gl_get_line() - can't read or write to the terminal without blocking. Thus in non- - blocking server mode, in order to determine when a NULL return value - signifies that an error occurred or not, it is necessary to call the - gl_return_status() function. If this function returns the enumerated - value, GLR_BLOCKED, as documented in the <a href="gl_get_line.html"><b>gl_get_line</b></a> man - page, this means that gl_get_line() is waiting for I/O, and no error - has occurred. - - When gl_get_line() returns NULL and gl_return_status() indicates that - this is due to blocked terminal I/O, the application should call - gl_get_line() again when the type of I/O reported by gl_pending_io() - becomes possible. The prompt, start_line and start_pos arguments of - gl_get_line() will be ignored on these calls. If you need to change - the prompt of the line that is currently being edited, then you can - call the gl_replace_prompt() function (documented in the - <a href="gl_get_line.html"><b>gl_get_line</b></a> man page) between calls to gl_get_line(). - - -</pre><h2>GIVING UP THE TERMINAL</h2><pre> - A complication that is unique to non-blocking server mode is that it - requires that the terminal be left in raw mode between calls to - gl_get_line(). If this weren't the case, the external event loop - wouldn't be able to detect individual key-presses, and the basic line - editing implemented by the terminal driver would clash with the editing - provided by gl_get_line(). What this means is that any time that the - terminal needs to be used for other things than entering a new input - line with gl_get_line(), it needs to be restored to a usable state. In - particular, whenever the process is suspended or terminated, the termi- - nal must be returned to a normal state. If this isn't done, then - depending on the characteristics of the shell that was used to invoke - the program, the user may end up with a hung terminal. To this end, the - gl_normal_io() function is provided for switching the terminal back to - the state that it was in when raw mode was last established. - - - int gl_normal_io(GetLine *gl); - - - What this function does is first flush any pending output to the termi- - nal, then move the cursor to the start of the terminal line which fol- - lows the end of the incompletely entered input line. At this point it - is safe to suspend or terminate the process, and it is safe for the - application to read and write to the terminal. To resume entry of the - input line, the application should call the gl_raw_io() function. - - - int gl_raw_io(GetLine *gl); - - - This function starts a new line, redisplays the partially completed - input line (if any), restores the cursor position within this line to - where it was when gl_normal_io() was called, then switches back to raw, - non-blocking terminal mode ready to continue entry of the input line - when gl_get_line() is next called. - - Note that in non-blocking server mode, if gl_get_line() is called after - a call to gl_normal_io(), without an intervening call to gl_raw_io(), - gl_get_line() will call gl_raw_mode() itself, and the terminal will - remain in this mode when gl_get_line() returns. - - -</pre><h2>SIGNAL HANDLING</h2><pre> - In the previous section it was pointed out that in non-blocking server - mode, the terminal must be restored to a sane state whenever a signal - is received that either suspends or terminates the process. In normal - I/O mode, this is done for you by gl_get_line(), but in non-blocking - server mode, since the terminal is left in raw mode between calls to - gl_get_line(), this signal handling has to be done by the application. - Since there are many signals that can suspend or terminate a process, - as well as other signals that are important to gl_get_line(), such as - the SIGWINCH signal, which tells it when the terminal size has changed, - the gl_tty_signals() function is provided for installing signal han- - dlers for all pertinent signals. - - - int gl_tty_signals(void (*term_handler)(int), - void (*susp_handler)(int), - void (*cont_handler)(int), - void (*size_handler)(int)); - - - What this does is use gl_get_line()'s internal list of signals to - assign specified signal handlers to groups of signals. The arguments of - this function are as follows. - - - term_handler - This is the signal handler that is to be - used to trap signals that by default - terminate any process that receives - them (eg. SIGINT or SIGTERM). - - susp_handler - This is the signal handler that is to be - used to trap signals that by default - suspend any process that receives them, - (eg. SIGTSTP or SIGTTOU). - - cont_handler - This is the signal handler that is to be - used to trap signals that are usually - sent when a process resumes after being - suspended (usually SIGCONT). Beware that there is - nothing to stop a user from sending one of these - signals at other times. - - size_handler - This signal handler is used to trap - signals that are sent to processes when - their controlling terminals are resized - by the user (eg. SIGWINCH). - - - These arguments can all be the same, if so desired, and you can specify - SIG_IGN (ignore this signal) or SIG_DFL (use the system-provided - default signal handler) instead of a function where pertinent. In par- - ticular, it is rarely useful to trap SIGCONT, so the cont_handler argu- - ment will usually be SIG_DFL or SIG_IGN. - - The gl_tty_signals() function uses the POSIX sigaction() function to - install these signal handlers, and it is careful to use the sa_mask - member of each sigaction structure to ensure that only one of these - signals is ever delivered at a time. This guards against different - instances of these signal handlers from simultaneously trying to write - to common global data, such as a shared sigsetjmp() buffer or a signal- - received flag. - - The signal handlers that are installed by this function, should call - the gl_handle_signal(). - - - void gl_handle_signal(int signo, GetLine *gl, int ngl); - - - The signo argument tells this function which signal it is being asked - to respond to, and the gl argument should be a pointer to the first - element of an array of ngl GetLine objects. If your application only - has one of these objects, just pass its pointer as the gl argument and - specify ngl as 1. - - Depending on the signal that is being handled, this function does dif- - ferent things. - - - Terminal resize signals (SIGWINCH) - If the signal indicates that the terminal was resized, then it arranges - for the next call to gl_get_line() to ask the terminal for its new size - and redraw the input line accordingly. In order that gl_get_line() be - called as soon as possible to do this, gl_handle_signal() also arranges - that the next call to gl_pending_io() will return GLP_WRITE. Thus if - the application waits for I/O in select() or poll(), then the applica- - tion needs to ensure that these functions will be reliably aborted when - a signal is caught and handled by the application. More on this below. - - -</pre><h2>Process termination signals.</h2><pre> - If the signal that was caught is one of those that by default termi- - nates any process that receives it, then gl_handle_signal() does the - following steps. - - 1. First it blocks the delivery of all signals that can be - blocked (ie. SIGKILL and SIGSTOP can't be blocked) - - 2. Next it calls gl_normal_io() for each of the ngl - GetLine objects. Note that this does nothing to any of the - GetLine objects that aren't currently in raw mode. - - 3. Next it sets the signal handler of the signal to its default, - process-termination disposition. - - 4. Next it re-sends the process the signal that was caught. - - 5. Finally it unblocks delivery of this signal, which - results in the process being terminated. - - -</pre><h2>Process suspension signals.</h2><pre> - If the default disposition of the signal is to suspend the process, the - same steps are executed as for process termination signals, except that - when the process is later resumed, gl_handle_signal() continues, and - does the following steps. - - 6. It re-blocks delivery of the signal. - - 7. It reinstates the signal handler of the signal to the one - that was displaced when its default disposition was substituted. - - 8. For any of the GetLine objects that were in raw mode when - gl_handle_signal() was called, gl_handle_signal() then - calls gl_raw_io(), to resume entry of the input lines on - those terminals. - - 9. Finally, it restores the signal process mask to how it - was when gl_handle_signal() was called. - - Note that the process is suspended or terminated using the original - signal that was caught, rather than using the uncatchable SIGSTOP and - SIGKILL signals. This is important, because when a process is suspended - or terminated, the parent of the process may wish to use the status - value returned by the wait() system call to figure out which signal was - responsible. In particular, most shells use this information to print a - corresponding message to the terminal. Users would be rightly confused - if when their process received a SIGPIPE signal, the program responded - by sending itself a SIGKILL signal, and the shell then printed out the - provocative statement, "Killed!". - - -</pre><h2>INTERRUPTING THE EVENT LOOP</h2><pre> - If a signal is caught and handled when the application's event loop is - waiting in select() or poll(), these functions will be aborted with - errno set to EINTR. When this happens the event loop should call - gl_pending_io(), before calling select() or poll() again. It should - then arrange for select() or poll() to wait for the type of I/O that - this reports. This is necessary, because any signal handler which calls - gl_handle_signal(), will frequently change the type of I/O that - gl_get_line() is waiting for. - - Unfortunately, if a signal arrives between the statements which config- - ure the arguments of select() or poll() and the calls to these func- - tions, then the signal will not be seen by these functions, which will - then not be aborted. If these functions are waiting for keyboard input - from the user when the signal is received, and the signal handler - arranges to redraw the input line to accomodate a terminal resize or - the resumption of the process, then this redisplay will be end up being - delayed until the user hits the next key. Apart from puzzling the user, - this clearly isn't a serious problem. However there is a way, albeit - complicated, to completely avoid this race condition. The following - steps illustrate this. - - 1. Block all of the signals that gl_get_line() catches, - by passing the signal set returned by gl_list_signals() to - sigprocmask(). - - 2. Call gl_pending_io() and set up the arguments of - select() or poll() accordingly. - - 3. Call sigsetjmp() with a non-zero savesigs argument. - - 4. Initially this sigsetjmp() statement will return zero, - indicating that control isn't resuming there after a matching - call to siglongjmp(). - - 5. Replace all of the handlers of the signals that gl_get_line() - is configured to catch, with a signal handler that first records - the number of the signal that was caught, in a file-scope variable, - then calls siglongjmp() with a non-zero value argument, to - return execution to the above sigsetjmp() - statement. Registering these signal handlers can conveniently be - done using the gl_tty_signals() function. - - 6. Set the file-scope variable that the above signal handler uses to - record any signal that is caught to -1, so that we can check - whether a signal was caught by seeing if it contains a valid signal - number. - - 7. Now unblock the signals that were blocked in step 1. Any signal - that was received by the process in between step 1 and now will - now be delivered, and trigger our signal handler, as will any - signal that is received until we block these signals again. - - 8. Now call select() or poll(). - - 9. When select() returns, again block the signals that were - unblocked in step 7. - - If a signal is arrived any time during the above steps, our signal han- - dler will be triggered and cause control to return to the sigsetjmp() - statement, where this time, sigsetjmp() will return non-zero, indicat- - ing that a signal was caught. When this happens we simply skip the - above block of statements, and continue with the following statements, - which are executed regardless of whether or not a signal is caught. - Note that when sigsetjmp() returns, regardless of why it returned, the - process signal mask is returned to how it was when sigsetjmp() was - called. Thus the following statements are always executed with all of - our signals blocked. - - 9. Reinstate the signal handlers that were displaced in step 5. - - 10. Check wether a signal was caught, by checking the file-scope - variable that the signal handler records signal numbers in. - - 11. If a signal was caught, send this signal to the application - again, and unblock just this signal, so that it invokes the - signal handler which we just reinstated in step 10. - - 12. Unblock all of the signals that were blocked in step 7. - - Since this is complicated, note that demo3.c includes a working example - of how to do this. The method used there however, is more general than - the above. What it provides is a wrapper function around select() which - encompasses steps 3 to 11. In this wrapper, rather than use - gl_list_signals() to figure out the signals to block, and and - gl_tty_signals() to assign and revert signal handlers, one of its argu- - ments is a sigset_t which specifies which signals to block and assign - signal handlers to. This function thus doesn't depend on gl_get_line() - and can thus be used in other situations where race-condition-free sig- - nal handling is required. - - -</pre><h2>SIGNALS CAUGHT BY GL_GET_LINE</h2><pre> - Since the application is expected to handle signals in non-blocking - server mode, gl_get_line() doesn't attempt to duplicate this when it is - being called. If one of the signals that it is configured to catch is - sent to the application while gl_get_line() is being called, - gl_get_line() reinstates the caller's signal handlers, then just before - returning, re-sends the signal to the process to let the application's - signal handler handle it. If the process isn't terminated by this sig- - nal, gl_get_line() returns NULL, and a following call to gl_return_sta- - tus() returns the enumerated value GLR_SIGNAL. - - -</pre><h2>ABORTING LINE INPUT</h2><pre> - Often, rather than letting it terminate the process, applications - respond to the SIGINT user-interrupt signal by aborting the current - input line. The way to do this in non-blocking server-I/O mode is to - not call gl_handle_signal() when this signal is caught, but instead to - call the gl_abandon_line(). - - - void gl_abandon_line(GetLine *gl); - - - This function arranges that when gl_get_line() is next called, it first - flushes any pending output to the terminal, then discardes the current - input line, outputs a new prompt on the next line, and finally starts - accepting input of a new input line from the user. - - -</pre><h2>SIGNAL SAFE FUNCTIONS</h2><pre> - Provided that certain rules are followed, the following functions can - have been written to be safely callable from signal handlers. Other - functions in this library should not be called from signal handlers. - - - gl_normal_io() - gl_raw_io() - gl_handle_signal() - gl_abandon_line() - - - In order for this to be true, all signal handlers that call these func- - tions must be registered in such a way that only one instance of any - one of them can be running at one time. The way to do this is to use - the POSIX sigaction() function to register all signal handlers, and - when doing this, use the sa_mask member of the corresponding sigaction - structure, to indicate that all of the signals who's handlers invoke - the above functions, should be blocked when the current signal is being - handled. This prevents two signal handlers from operating on a GetLine - object at the same time. - - To prevent signal handlers from accessing a GetLine object while - gl_get_line() or any of its associated public functions are operating - on it, all public functions associated with gl_get_line(), including - gl_get_line() itself, temporarily block the delivery of signals when - they are accessing GetLine objects. Beware that the only signals that - they block are the signals that gl_get_line() is currently configured - to catch, so be sure that if you call any of the above functions from - signal handlers, that the signals that these handlers are assigned to - are configured to be caught by gl_get_line() (see gl_trap_signal()). - - -</pre><h2>USING TIMEOUTS TO POLL</h2><pre> - If instead of using select() or poll() to wait for I/O, your applica- - tion just needs to get out of gl_get_line() periodically to briefly do - something else before returning to accept input from the user, this can - be done in non-blocking server mode by using the gl_inactivity_time- - out() function (see <a href="gl_get_line.html"><b>gl_get_line</b></a>), to specify that a - callback function that returns GLTO_CONTINUE should be called whenever - gl_get_line() has been waiting for I/O for more than a specified amount - of time. - - When this callback is triggered, gl_get_line() will return NULL, and a - following call to gl_return_status() will return GLR_BLOCKED. - - Beware that gl_get_line() won't return until the user hasn't typed a - key for the specified interval, so if the interval is long, and the - user keeps typing, gl_get_line() may not return for a while. In other - words there is no guarantee that it will return in the time specified. - - -</pre><h2>THE SERVER DEMO PROGRAM</h2><pre> - The demo3 program that is distributed with the library, provides a - working example of how to use non-blocking server I/O mode in a real - program. As far as the user is concerned, this program operates - identically to the main demo program (called demo), except that whereas - the main demo program uses the normal blocking I/O mode, demo3 using - non-blocking I/O and an external event loop. The source code can be - found in demo3.c, and the comments therein explain the various steps. - - -</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"><b>libtecla</b></a>, <a href="gl_get_line.html"><b>gl_get_line</b></a>, <a href="tecla.html"><b>tecla</b></a>, <a href="ef_expand_file.html"><b>ef_expand_file</b></a>, - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a>, <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="gl_io_mode.html"><b>gl_io_mode</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/index.html b/libtecla-1.6.1/html/index.html deleted file mode 100644 index 29889da..0000000 --- a/libtecla-1.6.1/html/index.html +++ /dev/null @@ -1,122 +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.6.1. This may be obtained from: -<P> - <a href="libtecla-1.6.1.tar.gz">http://www.astro.caltech.edu/~mcs/tecla/libtecla-1.6.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="tecla.html">tecla</a> - Documentation for users of programs which use gl_get_line(). -<LI> <a href="libtecla.html">libtecla</a> - A programmers introduction to the tecla library. -<LI> <a href="gl_get_line.html">gl_get_line</a> - The interactive line-input function. -<LI> <a href="gl_io_mode.html">gl_io_mode</a> - Using gl_get_line() in a non-blocking fashion. -<LI> <a href="cpl_complete_word.html">cpl_complete_word</a> - The word (eg. filename) completion function. -<LI> <a href="ef_expand_file.html">ef_expand_file</a> - The filename expansion function. -<LI> <a href="pca_lookup_file.html">pca_lookup_file</a> - A directory-list based filename lookup and completion module. -<LI> <a href="enhance.html">enhance</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,9 with any of gcc, Sun C, or g++. - Mandrake Linux 7.1 etc.., gcc - Red Hat Linux 7 etc.., gcc - Fedora Core 1, gcc - Suse Linux 6.4, gcc - IBM AIX 4.3.3, gcc - HP-UX 10.20, HP-UX 11, gcc, c89 - FreeBSD, gcc - Alpha OSF1, cc, gcc - Mac OS X - Cygwin (running under Windows) - QNX - NetBSD 1.6, 386, gcc - SGI IRIX 6.5 -</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,9 with any of gcc, Sun C, or g++. - Mandrake Linux, gcc - RedHat Linux, gcc - Fedora Core, gcc - SuSE Linux, gcc - HP-UX 11, gcc - IBM AIX 4.3.3, gcc - Alpha OSF1, cc - SGI IRIX 6.5 -</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 (31-Oct-2004) -</BODY> diff --git a/libtecla-1.6.1/html/libtecla.html b/libtecla-1.6.1/html/libtecla.html deleted file mode 100644 index 2b85d7a..0000000 --- a/libtecla-1.6.1/html/libtecla.html +++ /dev/null @@ -1,138 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="libtecla.html"><b>libtecla</b></a> <a href="libtecla.html"><b>libtecla</b></a> - - - -</pre><h2>NAME</h2><pre> - libtecla - An interactive command-line input library. - -</pre><h2>SYNOPSIS</h2><pre> - @CC@ ... -ltecla -lcurses - - -</pre><h2>DESCRIPTION</h2><pre> - The tecla library provides programs with interactive command line edit- - ing 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 the calling program. - - The various parts of the library are documented in the following man - pages: - - <a href="tecla.html"><b>tecla</b></a> - Use level documentation of the - command-line editing facilities - provided by gl_get_line(). - <a href="gl_get_line.html"><b>gl_get_line</b></a> - The interactive line-input module. - <a href="gl_io_mode.html"><b>gl_io_mode</b></a> - How to use gl_get_line() in an - incremental, non-blocking fashion. - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a> - The word completion module. - <a href="ef_expand_file.html"><b>ef_expand_file</b></a> - The filename expansion module. - <a href="pca_lookup_file.html"><b>pca_lookup_file</b></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"><b>enhance</b></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 read- - ing directory entries when doing filename completion. The reentrant - version of the library is usually called libtecla_r.a instead of libte- - cla.a, so if only the latter is available, it probably isn't the cor- - rect 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 comple- - tion of incomplete usernames in ~username/ expressions is disabled. - This doesn't disable expansion 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 formal 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 cen- - ters 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"><b>gl_get_line</b></a>, <a href="tecla.html"><b>tecla</b></a>, <a href="gl_io_mode.html"><b>gl_io_mode</b></a>, <a href="ef_expand_file.html"><b>ef_expand_file</b></a>, - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a>, <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a>, <a href="enhance.html"><b>enhance</b></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. - - - - <a href="libtecla.html"><b>libtecla</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/pca_lookup_file.html b/libtecla-1.6.1/html/pca_lookup_file.html deleted file mode 100644 index d5e1e7b..0000000 --- a/libtecla-1.6.1/html/pca_lookup_file.html +++ /dev/null @@ -1,312 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> - - - -</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 libte- - cla(@LIBR_MANEXT@) man page). - - PathCache objects allow an application to search for files in any colon - separated list of directories, such as the unix execution PATH environ- - ment variable. Files in absolute directories are cached in a PathCache - object, whereas relative directories are scanned as needed. Using a - PathCache object, you can look up the full pathname of a simple file- - name, 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 pro- - vided for only selecting specific types of files. The obvious applica- - tion of this facility is to provide Tab-completion and lookup of exe- - cutable 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 directories, such as - "/usr/bin:/home/mcs/bin:.". This can include directories specified by - absolute pathnames such as "/usr/bin", as well as sub-directories spec- - ified by relative pathnames such as "." or "bin". Files in the absolute - directories 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. Otherwise, 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 file- - name cache, is achieved by passing the provided pca_path_completions() - callback function to the cpl_complete_word() function (see the cpl_com- - plete_word(@FUNC_MANEXT@) man page). - - CPL_MATCH_FN(pca_path_completions); - - This callback requires that its data argument be a pointer to a PcaP- - athConf 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 functions which allow you to individually change - these parameters are discussed below. - - By default, the pca_path_completions() callback function searches back- - wards 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 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 completion and lookup functions to - be selective in the filenames that they return. This is done by regis- - tering 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 per- - missions of the file and the permissions of its parent directories, and - only returns 1 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 PATH environment vari- - able. The example program given earlier in this man page provides a - demonstration of this. - - Beware that if somebody tries to complete an empty string, your call- - back will get called once for every file in the cache, which could num- - ber 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. - - 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 pca_scan_path() - is called, and whenever pca_set_check_fn() is called with changed call- - back function or data arguments. - - -</pre><h2>ERROR HANDLING</h2><pre> - If pca_scan_path() reports that an error occurred by returning 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 completion in ~username/ expressions, in cpl_path_comple- - tions(). - - Using the libtecla_r.a 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 PathCache object. In other words, if - two threads want to do path searching, they should each call new_Path- - Cache() 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"><b>libtecla</b></a>, <a href="gl_get_line.html"><b>gl_get_line</b></a>, <a href="ef_expand_file.html"><b>ef_expand_file</b></a>, - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/html/release.html b/libtecla-1.6.1/html/release.html deleted file mode 100644 index b048f4f..0000000 --- a/libtecla-1.6.1/html/release.html +++ /dev/null @@ -1,590 +0,0 @@ -<html><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.6.1: - - This is primarily a minor bug-fix release. - - One added feature is the ability to call gl_normal_io() from - callbacks registered by gl_watch_fd() and - gl_inactivity_timeout(). This allows these callbacks to cleanly - suspend line editing before either reading from the terminal, or - writing to the terminal; and then subsequently causes the input line - to be automatically redisplayed, and line-editing to be resumed by - gl_get_line(), as soon as the callback returns. - - Another minor change is that if the terminal type specified in the - TERM environment variable is set to "dumb", gl_get_line() now treats - the terminal as though it were a non-interactive stream, rather than - treating it as a VT100-compatible terminal. This means that it - doesn't either prompt for input, or perform any command-line - editing, even when it really is interacting with a terminal. This is - aimed at the rare situation where a third-pary program that connects - to libtecla through an embedded pseudo-terminal, needs to be forced - to behave as though it weren't talking to a terminal, in order that - it be useable in non-interactive scripts. - - Note that in the previous release, the optional configuration - function, gl_tty_signals(), was incorrectly swapping the suspend and - terminal signal handlers before installing them. - - A configuration problem that prevented select() from being used - under MacOS X, has been fixed. - - Although not documented in the man page, it was meant to be possible - to take the input line that one call to gl_get_line() returned, and - ask the next call to gl_get_line() to present it back to the user - for re-editing, simply by passing the pointer returned by one call - to gl_get_line() as the start_line argument of the next call to - gl_get_line(). This feature unfortunately stopped working in 1.6.0, - so this release restores it, and officially documents it in the man - page documentation of gl_get_line(). - - In the previous version of the library, calling gl_terminal_size() - on a system without SIGWINCH support, would crash the - application. This has been fixed. - - Libtecla now apparently compiles cleanly under IRIX. - -Version 1.6.0: - - This release is primarily a bug-fix release. However there are also - four new functions, so the minor version number has been - incremented to reflect this. - - Two of the new functions are gl_automatic_history() and - gl_append_history(). The former of these functions allows the - application to tell gl_get_line() not to automatically archive - entered lines in the history list. The second of these functions - allows the application to explicitly append a line to the history - list. Thus together, these two functions allow the calling - application to take over control of what is placed in the history - list. - - The third new function is gl_query_char(), which prompts the user - for a single character reply, which the user can then type without - having to hit return to enter it. Unless echoing is disabled, the - character that is entered is then displayed after the prompt, - and a newline is started. - - Finally, the 4th new function is gl_read_char(), which also reads - a single character from the user, but doesn't prompt the user, write - anything to the terminal, or disturb any partially entered input - line. It is thus safe to call this function not only from between - calls to gl_get_line(), but also from application callback - functions, even if gl_normal_io() hasn't been called. - - When using the history-search-backwards or history-search-forwards - actions, if the search prefix that the user typed, contains any of - the *,? or [ globbing characters, it is now treated as a glob - pattern to be matched against historical lines, instead of a simple - prefix. - - I have added a --without-file-system option to the configure - script. This is intended for use in embedded systems that either - don't have filesystems, or where the file-system code in libtecla is - seen as unwanted bloat. See the INSTALL document for details. - - Similarly, I also added a --without-file-actions option to the - configure script. This allows the application author/installer to - prevent users of gl_get_line() from accessing the filesystem with - the builtin actions of gl_get_line(). It does this by removing a - number of action functions, such as expand-filename, and list-glob, - and by changing the default behavior of other actions, such as - complete-word and list-or-eof, to show no completions. - - Now to the bugs that have been fixed. Version 1.5.0 had a lot of big - internal changes, so there are a number of bugs that needed to be - fixed. There was a bug which caused a crash if gl_load_history() - was called multiple times. There was another bug which caused a - prompt not to be displayed on the next line after switching from - reading input from a file to reading from the terminal. Also, in - tecla configuration files, backslash escaped characters within - key-binding key-sequences weren't being escaped. Thus ^\\ got - interpretted as a control-\ followed by a \ character instead of as - a control-\. There was a bug in the history recall mechanism which - caused the search prefix to be forgotten in certain complicated - usage scenarios. There was a minor memory leak in the - gl_configure_getline() function. Finally, if gl_get_line() was - aborted by a signal, or any other abnormal event, the value of errno - which originally indicated what had happened, got zeroed by the - code that restored the terminal to a usable state. Thus the - application couldn't figure out what had caused the error, apart - from by looking at gl_return_status(). All of these bugs have been - fixed. - - In the Makefile, there were a number of places where install-sh was - invoked without a path prefix. This has now been remedied. - - A fully functional workaround for a bug in Solaris' terminal I/O - code has also been implemented. This bug, which only manifested - itself in libtecla's uncommonly used non-blocking server I/O mode, - caused characters entered while in normal I/O mode, between calls to - gl_get_line() to be invisible to the next call to gl_get_line(), - until the user typed at least one more key after raw terminal mode - was restored. - - The Gnu autoconf config.guess and config.sub scripts have been - updated to their latest versions. Apparently the old versions that I - was previously using were too old to know about certain BSD ports. - -Version 1.5.0: - - This release includes several major new features for those using - gl_get_line(), shared library support in Darwin, better cross - compilation support, and various minor bug fixes. - - The biggest new feature is the option of a non-blocking I/O mode, in - which gl_get_line() can safely be called from an application's - external event-loop to incrementally read input lines from the user. - This feature is documented in the gl_io_mode(3) man page. - - In addition, there is now support for the definition of additional - word-completion action functions, which can then be bound to - different keys. See the documentation of the gl_completion_action() - function in the gl_get_line(3) man page. - - Externally defined action functions can also be defined, although - presently they don't have write access to the input line, so they - are restricted to operations that display information text to the - terminal, or modify the environment of the calling application in - some way. See the documentation of the gl_register_action() function - in the gl_get_line(3) man page. - - Some of the non-blocking I/O support functions can also be used for - improved signal handling in the normal blocking mode. In particular, - the gl_list_signals() and gl_catch_blocked() functions make it - easier to write reliable signal handling around gl_get_line(). The - new "RELIABLE SIGNAL HANDLING" section of the gl_get_line(3) man - page is intended as an introduction to this subject. - - Programs can now clear the terminal between calls to gl_get_line(), - by calling the new gl_erase_terminal() function. - - The gl_display_text() function, now used in the demos to display - introductory banners, is provided for formatting text according to - the width of the terminal. - - It is now possible to install inactivity timeout callbacks in - gl_get_line(), using the new gl_inactivity_timeout() function. - - The new gl_set_term_size() function allows the application to - explicitly set the terminal size, for cases, such as when one is - using a terminal at the end of a serial lineq, where the terminal - driver doesn't send the process a SIGWINCH when the terminal size - changes. - - The new gl_bind_keyseq() function provides a convenient - alternative to gl_configure_getline(), for binding or unbinding - one key-sequence at a time. - - gl_get_line()s signal handling, file-descriptor event-handling, - inactivity-timeout handling and server-mode non-blocking I/O - features now not only work when input is coming from a terminal, but - now also work when input is coming from non-interactive streams, - such as files and pipes. - - The history implementation has been re-written to make it more - efficient and easier to modify. The biggest user-level change is - that when recalling history lines using a search prefix, the same - line is no longer returned more than once in a row. Previously this - duplicate elimination only worked when one was recalling a line - without specifying a search prefix, and this was naively performed - by preventing neighboring duplicates from existing in the history - list, rather than by skipping duplicates at search time. - - In previous versions of the library, when gl_get_line() and its - associated public functions detected invalid arguments, or couldn't - allocate memory, etc, error messages were written to stderr. This - isn't appropriate for library functions, so instead of writing such - messages to stderr, these messages are now recorded in buffers - within the affected GetLine object. The latest error message can - then subsequently be queried by calling gl_error_message(). The use - of errno has also been expanded, and a new function called - gl_return_status() has been provided to expand on the cause of the - last return from gl_get_line(). - - User level usage and configuration information has now been split - out of the gl_get_line(3) man page into a separate tecla(7) man - page. The enhance(3) man page has also been renamed to enhance(1). - - When expanding "~/", gl_get_line() now checks for, and returns the - value of the HOME environment variable, if it exists, in preference - to looking up the directory of the current user in the password - file. - - When the terminal was resized to a narrower width, previous versions - of gl_get_line() would redraw the line higher up the terminal. This - bug has been fixed. A bug in history recall has also been fixed, in - which an error message was being generated if one attempted to - recall a line while the cursor was at the end of the longest - possible input line. A more serious bug, in which callbacks - registered by gl_watch_fd() weren't being called for write-events, - has also been fixed. Finally, a few minor fixes have been made to - improve support under QNX and Mac OS X. - - Beware that in this release, much of the underlying code has - undergone some radical re-work, so although backwards compatibility - of all documented features has been preserved, there may be some - lingering bugs that could break existing programs. So, if you plan - to use this version in production code, please test it as far as - possible within your application before releasing it to your - clients, and as always, please report any unexpected behavior. - -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></html> diff --git a/libtecla-1.6.1/html/tecla.html b/libtecla-1.6.1/html/tecla.html deleted file mode 100644 index 6f270c1..0000000 --- a/libtecla-1.6.1/html/tecla.html +++ /dev/null @@ -1,1120 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -<a href="tecla.html"><b>tecla</b></a> <a href="tecla.html"><b>tecla</b></a> - - - -</pre><h2>NAME</h2><pre> - tecla, teclarc - The user interface provided by the Tecla library. - -</pre><h2>DESCRIPTION</h2><pre> - This man page describes the command-line editing features that are - available to users of programs that read keyboard input via the Tecla - library. Users of the tcsh shell will find the default key-bindings - very familiar. Users of the bash shell will also find it quite famil- - iar, but with a few minor differences, most notably in how forward and - backward searches through the list of historical commands are per- - formed. There are two major editing modes, one with emacs-like key- - bindings and another with vi-like key-bindings. By default emacs mode - is enabled, but vi mode can alternatively be selected via the user's - configuration file. This file can also be used to change the bindings - of individual keys to suit the user's preferences. By default, tab com- - pletion is provided. If the application hasn't reconfigured this to - complete other types of symbols, then tab completion completes file- - names. - - -</pre><h2>KEY SEQUENCE NOTATION</h2><pre> - In the rest of this man page, and also in all Tecla configuration - files, key-sequences are expressed as follows. - - - ^A or C-a - This is a control-A, entered by pressing the control key at - the same time as the A key. - - \E or M- - In key-sequences, both of these notations can be entered - either by pressing the escape key, then the following key, or by - pressing the Meta key at the same time as the following 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. - - up - This refers to the up-arrow key. - - down - This refers to the down-arrow key. - - left - This refers to the left-arrow key. - - right - This refers to the right-arrow key. - - a - This is just a normal A key. - - - -</pre><h2>THE TECLA CONFIGURATION FILE</h2><pre> - By default, Tecla looks for a file called .teclarc in your home direc- - tory (ie. ~/.teclarc). If it finds this file, it reads it, interpret- - ing 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 unrecog- - nized control-sequence is typed, place the following line in the con- - figuration file: - - nobeep - - An example of a key binding line in the configuration file is the fol- - lowing. - - 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 fol- - lowing 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 printable 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 following 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 exam- - ple, by not specifying an action function, the following command - unbinds the default beginning-of-line action from the ^A key sequence: - - bind ^A - - If you create a ~/.teclarc configuration file, but it appears to have - no effect on the program, check the documentation of the program to see - if the author chose a different name for this file. - - -</pre><h2>FILENAME AND TILDE COMPLETION</h2><pre> - With the default key bindings, pressing the TAB key (aka. ^I) results - in Tecla attempting to complete the incomplete filename that precedes - the cursor. Tecla 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, then - Tecla 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, Tecla 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, Tecla 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(@LIBR_MANEXT@) man page for more details. - - -</pre><h2>FILENAME EXPANSION</h2><pre> - With the default key bindings, pressing ^X* causes Tecla to expand the - filename that precedes the cursor, replacing ~/ and ~user/ expressions - with the corresponding home directories, and replacing $envvar expres- - sions 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() func- - tion. See the <a href="ef_expand_file.html"><b>ef_expand_file</b></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. Alternatively, you can do the same with the ^P, and ^N - 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. - - 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 pre- - cedes 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", Tecla would recall the "ls -l get- - line.c" line. Pressing M-p again would recall the "ls ~/tecla/" line. - - Note that if the string that you are searching for, contains any of the - special characters, *, ?, or '[', then it is interpretted as a pattern - to be matched. Thus, cotinuing with the above example, after typing in - the list of commands shown, if you then typed: - - *tecla* - - and hit M-p, then the "emacs ~/tecla/getline.c" line would be recalled - first, since it contains the word tecla somewhere in the line, Simi- - larly, hitting M-p again, would recall the "ls ~/tecla/" line, and hit- - ting it once more would recall the "ls ~/tecla/" line. The pattern syn- - tax is the same as that described for filename expansion, in the - ef_expand_file(@LIBR_MANEXT@ man page. - - -</pre><h2>HISTORY FILES</h2><pre> - Authors of programs that use the Tecla library have the option of sav- - ing historical command-lines in a file before exiting, and subsequently - reading them back in from this file when the program is next started. - There is no standard name for this file, since it makes sense for each - application to use its own history file, so that commands from differ- - ent applications don't get mixed up. - - -</pre><h2>INTERNATIONAL CHARACTER SETS</h2><pre> - Since libtecla version 1.4.0, Tecla 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, - - 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 variables are defined, or the program - neglects to call setlocale, 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. - - - Meta keys and locales - Beware that in most locales other than the default C locale, meta char- - acters 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 compose key without unexpectedly triggering meta - key bindings. You can still invoke meta bindings, since there are actu- - ally two ways to do this. For example the binding M-c can also be - invoked by pressing the escape key momentarily, then pressing 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 generate 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 continue 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 dis- - played 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. - - - 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 laptop the xev program reports that pressing this key gen- - erates 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, fol- - lowed by ", followed by i. - - -</pre><h2>THE AVAILABLE KEY BINDING FUNCTIONS</h2><pre> - The following is a list of the editing functions provided by the Tecla - library. The names in the leftmost column of the list can be used in - configuration files to specify which function a given key or combina- - tion of keys should invoke. They are also used in the next two sections - to list the default key-bindings in emacs and vi modes. - - 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 Tecla 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. - - Under UNIX the terminal driver sets a number of special keys for cer- - tain 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 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. - - ^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 gener- - ated 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 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. - - To learn how to tell the Tecla library to use vi mode instead of the - default emacs editing mode, see the earlier section entitled THE TECLA - CONFIGURATION FILE. - - Under UNIX the terminal driver sets a number of special keys for cer- - tain 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 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 - 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 ta- - ble. Thus, once in command mode, when you type the letter i, for exam- - ple, 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 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). - - 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 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. - - 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 inter- - preted as a repeat count by most bindings. A notable exception is the - goto-column binding, which interprets 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 bind- - ings 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 function 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 it does in the vi editor itself. - So for example, in vi command 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>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"><b>libtecla</b></a>, <a href="gl_get_line.html"><b>gl_get_line</b></a>, <a href="gl_io_mode.html"><b>gl_io_mode</b></a>, <a href="ef_expand_file.html"><b>ef_expand_file</b></a>, - <a href="cpl_complete_word.html"><b>cpl_complete_word</b></a>, <a href="pca_lookup_file.html"><b>pca_lookup_file</b></a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - <a href="tecla.html"><b>tecla</b></a> -</pre> -</body> diff --git a/libtecla-1.6.1/install-sh b/libtecla-1.6.1/install-sh deleted file mode 100755 index e9de238..0000000 --- a/libtecla-1.6.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.6.1/ioutil.c b/libtecla-1.6.1/ioutil.c deleted file mode 100644 index daf02c9..0000000 --- a/libtecla-1.6.1/ioutil.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.h> - -#include "ioutil.h" - -static int _io_pad_line(GlWriteFn *write_fn, void *data, int c, int n); - -/*....................................................................... - * Display a left-justified string over multiple terminal lines, - * taking account of the specified width of the terminal. Optional - * indentation and an option prefix string can be specified to be - * displayed at the start of each new terminal line used, and if - * needed, a single paragraph can be broken across multiple calls. - * Note that literal newlines in the input string can be used to force - * a newline at any point, and that in order to allow individual - * paragraphs to be written using multiple calls to this function, - * unless an explicit newline character is specified at the end of the - * string, a newline will not be started at the end of the last word - * in the string. Note that when a new line is started between two - * words that are separated by spaces, those spaces are not output, - * whereas when a new line is started because a newline character was - * found in the string, only the spaces before the newline character - * are discarded. - * - * Input: - * write_fn GlWriteFn * The callback function to use to write the - * output. - * data void * A pointer to arbitrary data to be passed to - * write_fn() whenever it is called. - * fp FILE * The stdio stream to write to. - * indentation int The number of fill characters to use to - * indent the start of each new terminal line. - * prefix const char * An optional prefix string to write after the - * indentation margin at the start of each new - * terminal line. You can specify NULL if no - * prefix is required. - * suffix const char * An optional suffix string to draw at the end - * of the terminal line. The line will be padded - * where necessary to ensure that the suffix ends - * in the last column of the terminal line. If - * no suffix is desired, specify NULL. - * fill_char int The padding character to use when indenting - * and filling up to the suffix. - * term_width int The width of the terminal being written to. - * start int The number of characters already written to - * the start of the current terminal line. This - * is primarily used to allow individual - * paragraphs to be written over multiple calls - * to this function, but can also be used to - * allow you to start the first line of a - * paragraph with a different prefix or - * indentation than those specified above. - * string const char * The string to be written. - * Output: - * return int On error -1 is returned. Otherwise the - * return value is the terminal column index at - * which the cursor was left after writing the - * final word in the string. Successful return - * values can thus be passed verbatim to the - * 'start' arguments of subsequent calls to - * _io_display_text() to allow the printing of a - * paragraph to be broken across multiple calls - * to _io_display_text(). - */ -int _io_display_text(GlWriteFn *write_fn, void *data, int indentation, - const char *prefix, const char *suffix, int fill_char, - int term_width, int start, const char *string) -{ - int ndone; /* The number of characters written from string[] */ - int nnew; /* The number of characters to be displayed next */ - int was_space; /* True if the previous character was a space or tab */ - int last = start; /* The column number of the last character written */ - int prefix_len; /* The length of the optional line prefix string */ - int suffix_len; /* The length of the optional line prefix string */ - int margin_width; /* The total number of columns used by the indentation */ - /* margin and the prefix string. */ - int i; -/* - * Check the arguments? - */ - if(!string || !write_fn) { - errno = EINVAL; - return -1; - }; -/* - * Enforce sensible values on the arguments. - */ - if(term_width < 0) - term_width = 0; - if(indentation > term_width) - indentation = term_width; - else if(indentation < 0) - indentation = 0; - if(start > term_width) - start = term_width; - else if(start < 0) - start = 0; -/* - * Get the length of the prefix string. - */ - prefix_len = prefix ? strlen(prefix) : 0; -/* - * Get the length of the suffix string. - */ - suffix_len = suffix ? strlen(suffix) : 0; -/* - * How many characters are devoted to indenting and prefixing each line? - */ - margin_width = indentation + prefix_len; -/* - * Write as many terminal lines as are needed to display the whole string. - */ - for(ndone=0; string[ndone]; start=0) { - last = start; -/* - * Write spaces from the current position in the terminal line to the - * width of the requested indentation margin. - */ - if(indentation > 0 && last < indentation) { - if(_io_pad_line(write_fn, data, fill_char, indentation - last)) - return -1; - last = indentation; - }; -/* - * If a prefix string has been specified, display it unless we have - * passed where it should end in the terminal output line. - */ - if(prefix_len > 0 && last < margin_width) { - int pstart = last - indentation; - int plen = prefix_len - pstart; - if(write_fn(data, prefix+pstart, plen) != plen) - return -1; - last = margin_width; - }; -/* - * Locate the end of the last complete word in the string before - * (term_width - start) characters have been seen. To handle the case - * where a single word is wider than the available space after the - * indentation and prefix margins, always make sure that at least one - * word is printed after the margin, regardless of whether it won't - * fit on the line. The two exceptions to this rule are if an embedded - * newline is found in the string or the end of the string is reached - * before any word has been seen. - */ - nnew = 0; - was_space = 0; - for(i=ndone; string[i] && (last+i-ndone < term_width - suffix_len || - (nnew==0 && last==margin_width)); i++) { - if(string[i] == '\n') { - if(!was_space) - nnew = i-ndone; - break; - } else if(isspace((int) string[i])) { - if(!was_space) { - nnew = i-ndone+1; - was_space = 1; - }; - } else { - was_space = 0; - }; - }; -/* - * Does the end of the string delimit the last word that will fit on the - * output line? - */ - if(nnew==0 && string[i] == '\0') - nnew = i-ndone; -/* - * Write the new line. - */ - if(write_fn(data, string+ndone, nnew) != nnew) - return -1; - ndone += nnew; - last += nnew; -/* - * Start a newline unless we have reached the end of the input string. - * In the latter case, in order to give the caller the chance to - * concatenate multiple calls to _io_display_text(), omit the newline, - * leaving it up to the caller to write this. - */ - if(string[ndone] != '\0') { -/* - * If a suffix has been provided, pad out the end of the line with spaces - * such that the suffix will end in the right-most terminal column. - */ - if(suffix_len > 0) { - int npad = term_width - suffix_len - last; - if(npad > 0 && _io_pad_line(write_fn, data, fill_char, npad)) - return -1; - last += npad; - if(write_fn(data, suffix, suffix_len) != suffix_len) - return -1; - last += suffix_len; - }; -/* - * Start a new line. - */ - if(write_fn(data, "\n", 1) != 1) - return -1; -/* - * Skip any spaces and tabs that follow the last word that was written. - */ - while(string[ndone] && isspace((int)string[ndone]) && - string[ndone] != '\n') - ndone++; -/* - * If the terminating character was a literal newline character, - * skip it in the input string, since we just wrote it. - */ - if(string[ndone] == '\n') - ndone++; - last = 0; - }; - }; -/* - * Return the column number of the last character printed. - */ - return last; -} - -/*....................................................................... - * Write a given number of spaces to the specified stdio output string. - * - * Input: - * write_fn GlWriteFn * The callback function to use to write the - * output. - * data void * A pointer to arbitrary data to be passed to - * write_fn() whenever it is called. - * c int The padding character. - * n int The number of spaces to be written. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _io_pad_line(GlWriteFn *write_fn, void *data, int c, int n) -{ - enum {FILL_SIZE=20}; - char fill[FILL_SIZE+1]; -/* - * Fill the buffer with the specified padding character. - */ - memset(fill, c, FILL_SIZE); - fill[FILL_SIZE] = '\0'; -/* - * Write the spaces using the above literal string of spaces as - * many times as needed to output the requested number of spaces. - */ - while(n > 0) { - int nnew = n <= FILL_SIZE ? n : FILL_SIZE; - if(write_fn(data, fill, nnew) != nnew) - return 1; - n -= nnew; - }; - return 0; -} - -/*....................................................................... - * The following is an output callback function which uses fwrite() - * to write to the stdio stream specified via its callback data argument. - * - * Input: - * data void * The stdio stream to write to, specified via a - * (FILE *) pointer cast to (void *). - * s const char * The string to be written. - * n int The length of the prefix of s[] to attempt to - * write. - * Output: - * return int The number of characters written from s[]. This - * should normally be a number in the range 0 to n. - * To signal that an I/O error occurred, return -1. - */ -GL_WRITE_FN(_io_write_stdio) -{ - int ndone; /* The total number of characters written */ - int nnew; /* The number of characters written in the latest write */ -/* - * The callback data is the stdio stream to write to. - */ - FILE *fp = (FILE *) data; -/* - * Because of signals we may need to do more than one write to output - * the whole string. - */ - for(ndone=0; ndone<n; ndone += nnew) { - int nmore = n - ndone; - nnew = fwrite(s, sizeof(char), nmore, fp); - if(nnew < nmore) { - if(errno == EINTR) - clearerr(fp); - else - return ferror(fp) ? -1 : ndone + nnew; - }; - }; - return ndone; -} - diff --git a/libtecla-1.6.1/ioutil.h b/libtecla-1.6.1/ioutil.h deleted file mode 100644 index b9e8f16..0000000 --- a/libtecla-1.6.1/ioutil.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef ioutil_h -#define ioutil_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/*....................................................................... - * Callback functions of the following type can be registered to write - * to a terminal, when the default blocking writes to a local terminal - * aren't appropriate. In particular, if you don't want gl_get_line() - * to block, then this function should return before writing the - * specified number of characters if doing otherwise would involve - * waiting. - * - * Input: - * data void * The anonymous data pointer that was registered with - * this callback function. - * s const char * The string to be written. Beware that this string - * may not have a terminating '\0' character. - * n int The length of the prefix of s[] to attempt to - * write. - * Output: - * return int The number of characters written from s[]. This - * should normally be a number in the range 0 to n. - * To signal that an I/O error occurred, return -1. - */ -#define GL_WRITE_FN(fn) int (fn)(void *data, const char *s, int n) -typedef GL_WRITE_FN(GlWriteFn); - -/* - * The following output callback function requires a (FILE *) callback - * data argument, and writes to this stream using the fwrite stdio - * function. - */ -GL_WRITE_FN(_io_write_stdio); - -/* - * Left justify text within the bounds of the terminal adding optional - * indentation, prefixes and suffixes to each line if requested. - */ -int _io_display_text(GlWriteFn *write_fn, void *data, int indentation, - const char *prefix, const char *suffix, int fill_char, - int term_width, int start, const char *string); - -#endif diff --git a/libtecla-1.6.1/keytab.c b/libtecla-1.6.1/keytab.c deleted file mode 100644 index 0820960..0000000 --- a/libtecla-1.6.1/keytab.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.h> - -#include "keytab.h" -#include "strngmem.h" -#include "getline.h" -#include "errmsg.h" -#include "hash.h" - -/* - * 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. - */ -struct KeyTab { - ErrMsg *err; /* Information about the last error */ - 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 */ -}; - -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, - void *data); -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); -static KtKeyMatch _kt_locate_keybinding(KeyTab *kt, const char *binary_keyseq, - int nc, int *first, int *last); - -/*....................................................................... - * 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) { - errno = ENOMEM; - 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->err = NULL; - kt->size = KT_TABLE_INC; - kt->nkey = 0; - kt->table = NULL; - kt->actions = NULL; - kt->smem = NULL; -/* - * Allocate a place to record error messages. - */ - kt->err = _new_ErrMsg(); - if(!kt->err) - return _del_KeyTab(kt); -/* - * Allocate the table. - */ - kt->table = (KeySym *) malloc(sizeof(kt->table[0]) * kt->size); - if(!kt->table) { - errno = ENOMEM; - 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(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(kt->smem, 1); - kt->err = _del_ErrMsg(kt->err); - 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) { - _err_record_msg(kt->err, "Can't extend keybinding table", END_ERR_MSG); - errno = ENOMEM; - 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 */ - void *data; /* The callback data of the action function */ -/* - * Check arguments. - */ - if(kt==NULL || !keyseq) { - errno = EINVAL; - if(kt) - _err_record_msg(kt->err, "NULL argument(s)", END_ERR_MSG); - return 1; - }; -/* - * Lookup the function that implements the specified action. - */ - if(!action) { - keyfn = 0; - data = NULL; - } else { - Symbol *sym = _find_HashSymbol(kt->actions, action); - if(!sym) { - _err_record_msg(kt->err, "Unknown key-binding action: ", action, - END_ERR_MSG); - errno = EINVAL; - return 1; - }; - keyfn = (KtKeyFn *) sym->fn; - data = sym->data; - }; -/* - * Record the action in the table. - */ - return _kt_set_keyfn(kt, binder, keyseq, keyfn, data); -} - -/*....................................................................... - * 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. - * data void * A pointer to anonymous data to be passed to keyfn - * whenever it is called. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _kt_set_keyfn(KeyTab *kt, KtBinder binder, const char *keyseq, - KtKeyFn *keyfn, void *data) -{ - 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 */ - int i; -/* - * Check arguments. - */ - if(kt==NULL || !keyseq) { - errno = EINVAL; - if(kt) - _err_record_msg(kt->err, "NULL argument(s)", END_ERR_MSG); - 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) { - errno = ENOMEM; - _err_record_msg(kt->err, "Insufficient memory to record key sequence", - END_ERR_MSG); - 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_locate_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, data); - } 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) { - _err_record_msg(kt->err, "Can't bind \"", keyseq, - "\", because it is a prefix of another binding", - END_ERR_MSG); - binary = _del_StringMemString(kt->smem, binary); - errno = EPERM; - 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; - for(i=0; i<KTB_NBIND; i++) { - KtAction *action = sym->actions + i; - action->fn = 0; - action->data = NULL; - }; - sym->binder = -1; - _kt_assign_action(sym, binder, keyfn, data); - 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. - */ -static KtKeyMatch _kt_locate_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() */ -/* - * 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; -} - -/*....................................................................... - * Lookup the sub-array of key-bindings who's key-sequences minimally - * match a given key-sequence. - * - * 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: - * matches KeySym ** The array of minimally matching symbols - * can be found in (*matches)[0..nmatch-1], unless - * no match was found, in which case *matches will - * be set to NULL. - * nmatch int The number of ambiguously matching symbols. This - * will be 0 if there is no match, 1 for an exact - * match, and a number greater than 1 for an ambiguous - * match. - * 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, KeySym **matches, int *nmatch) -{ - KtKeyMatch status; /* The return status */ - int first,last; /* The indexes of the first and last matching entry */ - /* in the symbol table. */ -/* - * Check the arguments. - */ - if(!kt || !binary_keyseq || !matches || !nmatch || nc < 0) { - errno = EINVAL; - if(kt) - _err_record_msg(kt->err, "NULL argument(s)", END_ERR_MSG); - return KT_BAD_MATCH; - }; -/* - * Lookup the indexes of the binding-table entries that bracket the - * target key-sequence. - */ - status = _kt_locate_keybinding(kt, binary_keyseq, nc, &first, &last); -/* - * Translate the indexes into the corresponding subarray of matching - * table entries. - */ - switch(status) { - case KT_EXACT_MATCH: - case KT_AMBIG_MATCH: - *matches = kt->table + first; - *nmatch = last - first + 1; - break; - default: - *matches = NULL; - *nmatch = 0; - break; - }; - return status; -} - -/*....................................................................... - * 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[] */ - char c; /* An intermediate character */ -/* - * 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]) { -/* - * Get the next, possibly escaped, character. - */ - if(iptr[1] == '\\') { - c = _kt_backslash_escape(iptr+2, &iptr); - } else { - c = iptr[1]; - iptr += 2; - }; -/* - * Convert the character to a control character. - */ - *optr++ = MAKE_CTRL(c); - } 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. - * data void * A pointer to arbitrary callback data to pass to the - * action function whenever it is called. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _kt_set_action(KeyTab *kt, const char *action, KtKeyFn *fn, void *data) -{ - Symbol *sym; /* The symbol table entry of the action */ -/* - * Check the arguments. - */ - if(!kt || !action) { - errno = EINVAL; - if(kt) - _err_record_msg(kt->err, "NULL argument(s)", END_ERR_MSG); - 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; - sym->data = data; - return 0; - }; -/* - * Add a new action. - */ - if(!_new_HashSymbol(kt->actions, action, 0, (void (*)(void))fn, data, 0)) { - _err_record_msg(kt->err, "Insufficient memory to record key-binding action", - END_ERR_MSG); - 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. - * data void * A pointer to arbitrary callback data to pass to - * the action function whenever it is called. - */ -static void _kt_assign_action(KeySym *sym, KtBinder binder, KtKeyFn *keyfn, - void *data) -{ - KtAction *action; /* An action function/data pair */ - int i; -/* - * Unknown binding source? - */ - if(binder < 0 || binder >= KTB_NBIND) - return; -/* - * Record the action according to its source. - */ - action = sym->actions + binder; - action->fn = keyfn; - action->data = data; -/* - * Find the highest priority binding source that has supplied an - * action. Note that the actions[] array is ordered in order of - * descreasing priority, so the first entry that contains a function - * is the one to use. - */ - for(i=0; i<KTB_NBIND && !sym->actions[i].fn; i++) - ; -/* - * Record the index of this action for use during lookups. - */ - sym->binder = i < KTB_NBIND ? i : -1; - 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, NULL); -/* - * 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->binder < 0) { - _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) { - errno = EINVAL; - if(kt) - _err_record_msg(kt->err, "NULL argument(s)", END_ERR_MSG); - 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; -} - -/*....................................................................... - * Lookup the function that implements a given action. - * - * Input: - * kt KeyTab * The table of key bindings. - * action const char * The name of the action to look up. - * Input/Output: - * fn KtKeyFn ** If the action is found, the function that - * implements it will be assigned to *fn. Note - * that fn can be NULL. - * data void ** If the action is found, the callback data - * associated with the action function, will be - * assigned to *data. Note that data can be NULL. - * Output: - * return int 0 - OK. - * 1 - Action not found. - */ -int _kt_lookup_action(KeyTab *kt, const char *action, - KtKeyFn **fn, void **data) -{ - Symbol *sym; /* The symbol table entry of the action */ -/* - * Check the arguments. - */ - if(!kt || !action) { - errno = EINVAL; - if(kt) - _err_record_msg(kt->err, "NULL argument(s)", END_ERR_MSG); - return 1; - }; -/* - * Lookup the symbol table entry of the action. - */ - sym = _find_HashSymbol(kt->actions, action); - if(!sym) - return 1; -/* - * Return the function and ccallback data associated with the action. - */ - if(fn) - *fn = (KtKeyFn *) sym->fn; - if(data) - *data = sym->data; - return 0; -} - -/*....................................................................... - * Return extra information (ie. in addition to that provided by errno) - * about the last error to occur in any of the public functions of this - * module. - * - * Input: - * kt KeyTab * The table of key bindings. - * Output: - * return const char * A pointer to the internal buffer in which - * the error message is temporarily stored. - */ -const char *_kt_last_error(KeyTab *kt) -{ - return kt ? _err_get_msg(kt->err) : "NULL KeyTab argument"; -} diff --git a/libtecla-1.6.1/keytab.h b/libtecla-1.6.1/keytab.h deleted file mode 100644 index b275c98..0000000 --- a/libtecla-1.6.1/keytab.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef keytab_h -#define keytab_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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" - -/*-----------------------------------------------------------------------* - * 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. - * data void * A pointer to action-specific data, - * cast to (void *). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -#define KT_KEY_FN(fn) int (fn)(GetLine *gl, int count, void *data) - -typedef KT_KEY_FN(KtKeyFn); - -/* - * Allow the association of arbitrary callback data with each action - * function. - */ -typedef struct { - KtKeyFn *fn; /* The acion function */ - void *data; /* A pointer to arbitrary data to be passed to */ - /* fn() whenever it is called. */ -} KtAction; - -/* - * Enumerate the possible sources of key-bindings in order of decreasing - * priority. - */ -typedef enum { - KTB_USER, /* This is a binding being set by the user */ - KTB_NORM, /* This is the default binding set by the library */ - KTB_TERM, /* This is a binding taken from the terminal settings */ -/* The following entry must always be last */ - KTB_NBIND /* The number of binding sources listed above */ -} KtBinder; - -/* - * 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[] */ - KtAction actions[KTB_NBIND]; /* Bindings from different sources */ - int binder; /* The index of the highest priority element */ - /* of actions[] that has been assigned an */ - /* action function, or -1 if none have. */ -} KeySym; - -/* - * Provide an opaque type alias to the symbol table container. - */ -typedef struct KeyTab KeyTab; - -/* - * Create a new symbol table. - */ -KeyTab *_new_KeyTab(void); - -/* - * Delete the symbol table. - */ -KeyTab *_del_KeyTab(KeyTab *kt); - -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 *fn, void *data); - -int _kt_set_action(KeyTab *kt, const char *action, KtKeyFn *fn, void *data); - -/* - * Lookup the function that implements a given action. - */ -int _kt_lookup_action(KeyTab *kt, const char *action, - KtKeyFn **fn, void **data); - -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, KeySym **matches, int *nmatch); - -/* - * 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); - -/* - * Get information about the last error in this module. - */ -const char *_kt_last_error(KeyTab *kt); - -#endif diff --git a/libtecla-1.6.1/libtecla.h b/libtecla-1.6.1/libtecla.h deleted file mode 100644 index fbbf220..0000000 --- a/libtecla-1.6.1/libtecla.h +++ /dev/null @@ -1,1834 +0,0 @@ -#ifndef libtecla_h -#define libtecla_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 */ -#include <signal.h> /* struct sigaction */ - -/* - * 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 6 -#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); - -/*....................................................................... - * Prompt the user for a single-character reply. - * - * Input: - * gl GetLine * A resource object returned by new_GetLine(). - * prompt char * The prompt to prefix the query with, or NULL - * to reuse the previous prompt. - * defchar char The character to substitute if the - * user simply hits return, or '\n' if you don't - * need to substitute anything. - * Output: - * return int The character that was read, or EOF if the read - * had to be aborted (in which case you can call - * gl_return_status() to find out why). - */ -int gl_query_char(GetLine *gl, const char *prompt, char defchar); - -/*....................................................................... - * Read a single uninterpretted character from the user, without - * displaying anything. - * - * Input: - * gl GetLine * A resource object previously returned by - * new_GetLine(). - * Output: - * return int The character that was read, or EOF if the read - * had to be aborted (in which case you can call - * gl_return_status() to find out why). - */ -int gl_read_char(GetLine *gl); - -/* - * 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 following enumerators specify the origin of a key binding, and - * are listed in order of decreasing priority, such that user-specified - * key-bindings take precedence over application default bindings. - */ -typedef enum { - GL_USER_KEY, /* A key-binding specified by the user */ - GL_APP_KEY /* A key-binding specified by the application */ -} GlKeyOrigin; - -/* - * Bind a key sequence to a given action. If action==NULL, unbind the - * key-sequence. - */ -int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq, - const char *action); - -/*----------------------------------------------------------------------- - * 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); - -/*....................................................................... - * This function allows you to install alternate completion action - * functions or completion listing functions, or to change the - * completion function of an existing action of the same type. This - * should preferably be called before the first call to gl_get_line() - * so that the name of the action becomes defined before the user's - * configuration file is read. - * - * 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. - * list_only int If non-zero, install an action that only lists - * possible completions, rather than attempting - * to perform the completion. - * name const char * The name with which users can refer to the - * binding in tecla configuration files. - * keyseq const char * The key sequence with which to invoke - * the binding. This should be specified in the - * same manner as key-sequences in tecla - * configuration files (eg. "M-^I"). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, - int list_only, const char *name, const char *keyseq); - -/*....................................................................... - * 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; - -/*....................................................................... - * On systems that have the select() system call, 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_inactivity_timeout(). 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); - -/* - * Enumerators from the following list are returned by activity - * timeout callbacks registered by gl_inactivity_timeout(). They tell - * gl_get_line() whether and how to procede. - */ -typedef enum { - GLTO_ABORT, /* Cause gl_get_line() to abort with an error */ - GLTO_REFRESH, /* Redraw the input line and continue waiting for input */ - GLTO_CONTINUE /* Continue to wait for input, without redrawing the line */ -} GlAfterTimeout; - -/*....................................................................... - * On systems that have the select() system call, the application has - * the option of providing a callback function of the following type, - * which is called whenever no terminal input or other I/O activity is - * seen for the timeout duration specified in the last call to - * gl_inactivity_timeout(). - * - * Input: - * gl GetLine * The gl_get_line() resource object. You can use - * this safely to call gl_watch_fd() or - * gl_inactivity_timeout(). 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_inactivity_timeout(). - * Output: - * return GlAfterTimeout GLTO_ABORT - Cause gl_get_line() to - * abort with an error (set - * errno if you need it). - * GLTO_REFRESH - Redraw the input line and - * continue waiting for - * input. Use this if you - * wrote something to the - * terminal. - * GLTO_CONTINUE - Continue to wait for - * input, without redrawing - * the line. - */ -#define GL_TIMEOUT_FN(fn) GlAfterTimeout (fn)(GetLine *gl, void *data) -typedef GL_TIMEOUT_FN(GlTimeoutFn); - -/*....................................................................... - * On systems with the select() system call, the gl_inactivity_timeout() - * function provides the option of setting (or cancelling) an - * inactivity timeout. Inactivity, in this case, refers both to - * terminal input received from the user, and to I/O on any file - * descriptors registered by calls to gl_watch_fd(). If at any time, - * no activity is seen for the requested time period, the specified - * timeout callback function is called. On returning, this callback - * returns a code which tells gl_get_line() what to do next. Note that - * each call to gl_inactivity_timeout() replaces any previously installed - * timeout callback, and that specifying a callback of 0, turns off - * inactivity timing. - * - * Beware that although the timeout argument includes a nano-second - * component, few computer clocks presently have resolutions finer - * than a few milliseconds, so asking for less than a few milliseconds - * is equivalent to zero on a lot of systems. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * callback GlTimeoutFn * The function to call when the inactivity - * timeout is exceeded. To turn off - * inactivity timeouts altogether, send 0. - * data void * A pointer to arbitrary data to pass to the - * callback function. - * sec unsigned long The number of whole seconds in the timeout. - * nsec unsigned long The fractional number of seconds in the - * timeout, expressed in nano-seconds (see - * the caveat above). - * 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_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data, - unsigned long sec, unsigned long nsec); - -/*....................................................................... - * 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); - -/*....................................................................... - * Tell gl_get_line() the current terminal size. Note that this is only - * necessary on systems where changes in terminal size aren't reported - * via SIGWINCH. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * ncolumn int The number of columns in the terminal. - * nline int The number of rows in the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_set_term_size(GetLine *gl, int ncolumn, int 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); - -/*....................................................................... - * Enable or disable the automatic addition of newly entered lines to the - * history list. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * enable int If true, subsequently entered lines will - * automatically be added to the history list - * before they are returned to the caller of - * gl_get_line(). If 0, the choice of how and - * when to archive lines in the history list, - * is left up to the calling application, which - * can do so via calls to gl_append_history(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_automatic_history(GetLine *gl, int enable); - -/*....................................................................... - * Append a specified line to the history list. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * line const char * The line to be added. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_append_history(GetLine *gl, const char *line); - -/*....................................................................... - * 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); - -/*....................................................................... - * By default, gl_get_line() doesn't trap signals that are blocked - * when it is called. This default can be changed either on a - * per-signal basis by calling gl_trap_signal(), or on a global basis - * by calling this function. What this function does is add the - * GLS_UNBLOCK_SIG flag to all signals that are currently configured - * to be trapped by gl_get_line(), such that when subsequent calls to - * gl_get_line() wait for I/O, these signals are temporarily - * unblocked. This behavior is useful in non-blocking server-I/O mode, - * where it is used to avoid race conditions related to handling these - * signals externally to gl_get_line(). See the demonstration code in - * demo3.c, or the gl_handle_signal() man page for further - * information. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - */ -void gl_catch_blocked(GetLine *gl); - -/*....................................................................... - * In server-I/O mode the terminal is left in raw mode between calls - * to gl_get_line(), so it is necessary for the application to install - * terminal restoring signal handlers for signals that could terminate - * or suspend the process, plus a terminal reconfiguration handler to - * be called when a process resumption signal is received, and finally - * a handler to be called when a terminal-resize signal is received. - * - * Since there are many signals that by default terminate or suspend - * processes, and different systems support different sub-sets of - * these signals, this function provides a convenient wrapper around - * sigaction() for assigning the specified handlers to all appropriate - * signals. It also arranges that when any one of these signals is - * being handled, all other catchable signals are blocked. This is - * necessary so that the specified signal handlers can safely call - * gl_raw_io(), gl_normal_io() and gl_update_size() without reentrancy - * issues. - * - * Input: - * term_handler void (*)(int) The signal handler to invoke when - * a process terminating signal is - * received. - * susp_handler void (*)(int) The signal handler to invoke when - * a process suspending signal is - * received. - * cont_handler void (*)(int) The signal handler to invoke when - * a process resumption signal is - * received (ie. SIGCONT). - * size_handler void (*)(int) The signal handler to invoke when - * a terminal-resize signal (ie. SIGWINCH) - * is received. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int), - void (*cont_handler)(int), void (*size_handler)(int)); - -/*....................................................................... - * 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(GetLine *gl); - -/*....................................................................... - * Return the signal mask used by gl_get_line(). This is the set of - * signals that gl_get_line() is currently configured to trap. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * set sigset_t * The set of signals will be returned in *set, - * in the form of a signal process mask, as - * used by sigaction(), sigprocmask(), - * sigpending(), sigsuspend(), sigsetjmp() and - * other standard POSIX signal-aware - * functions. - * Output: - * return int 0 - OK. - * 1 - Error (examine errno for reason). - */ -int gl_list_signals(GetLine *gl, sigset_t *set); - -/*....................................................................... - * Respond to signals who's default effects have important - * consequences to gl_get_line(). This is intended for use in - * non-blocking server mode, where the external event loop is - * responsible for catching signals. Signals that are handled include - * those that by default terminate or suspend the process, and the - * signal that indicates that the terminal size has changed. Note that - * this function is not signal safe and should thus not be called from - * a signal handler itself. See the gl_io_mode() man page for how it - * should be used. - * - * In the case of signals that by default terminate or suspend - * processes, command-line editing will be suspended, the terminal - * returned to a usable state, then the default disposition of the - * signal restored and the signal resent, in order to suspend or - * terminate the process. If the process subsequently resumes, - * command-line editing is resumed. - * - * In the case of signals that indicate that the terminal has been - * resized, the new size will be queried, and any input line that is - * being edited will be redrawn to fit the new dimensions of the - * terminal. - * - * Input: - * signo int The number of the signal to respond to. - * gl GetLine * The first element of an array of 'ngl' GetLine - * objects. - * ngl int The number of elements in the gl[] array. Normally - * this will be one. - */ -void gl_handle_signal(int signo, GetLine *gl, int ngl); - -/*....................................................................... - * Return extra information (ie. in addition to that provided by errno) - * about the last error to occur in either gl_get_line() or its - * associated public functions. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * buff char * An optional output buffer. Note that if the - * calling application calls any gl_*() - * functions from signal handlers, it should - * provide a buffer here, so that a copy of - * the latest error message can safely be made - * while signals are blocked. - * n size_t The allocated size of buff[]. - * Output: - * return const char * A pointer to the error message. This will - * be the buff argument, unless buff==NULL, in - * which case it will be a pointer to an - * internal error buffer. In the latter case, - * note that the contents of the returned buffer - * will change on subsequent calls to any gl_*() - * functions. - */ -const char *gl_error_message(GetLine *gl, char *buff, size_t n); - -/*....................................................................... - * Clear the terminal and leave the cursor at the home position. In - * server I/O mode, arrange for the input line to be redrawn from scratch - * when gl_get_line() is next called. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_erase_terminal(GetLine *gl); - -/*....................................................................... - * Display a left-justified string over multiple terminal lines, - * taking account of the current width of the terminal. Optional - * indentation and an optional prefix string can be specified to be - * displayed at the start of each new terminal line used. Similarly, - * an optional suffix can be specified to be displayed at the end of - * each terminal line. If needed, a single paragraph can be broken - * across multiple calls. Note that literal newlines in the input - * string can be used to force a newline at any point and that you - * should use this feature to explicitly end all paragraphs, including - * at the end of the last string that you write. Note that when a new - * line is started between two words that are separated by spaces, - * those spaces are not output, whereas when a new line is started - * because a newline character was found in the string, only the - * spaces before the newline character are discarded. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * indentation int The number of spaces of indentation to write - * at the beginning of each new terminal line. - * prefix const char * An optional prefix string to write after the - * indentation margin at the start of each new - * terminal line. You can specify NULL if no - * prefix is required. - * suffix const char * An optional suffix string to draw at the end - * of the terminal line. Spaces will be added - * where necessary to ensure that the suffix ends - * in the last column of the terminal line. If - * no suffix is desired, specify NULL. - * fill_char int The padding character to use when indenting - * the line or padding up to the suffix. - * def_width int If the terminal width isn't known, such as when - * writing to a pipe or redirecting to a file, - * this number specifies what width to assume. - * start int The number of characters already written to - * the start of the current terminal line. This - * is primarily used to allow individual - * paragraphs to be written over multiple calls - * to this function, but can also be used to - * allow you to start the first line of a - * paragraph with a different prefix or - * indentation than those specified above. - * string const char * The string to be written. - * Output: - * return int On error -1 is returned. Otherwise the - * return value is the terminal column index at - * which the cursor was left after writing the - * final word in the string. Successful return - * values can thus be passed verbatim to the - * 'start' arguments of subsequent calls to - * gl_display_text() to allow the printing of a - * paragraph to be broken across multiple calls - * to gl_display_text(). - */ -int gl_display_text(GetLine *gl, int indentation, const char *prefix, - const char *suffix, int fill_char, int def_width, - int start, const char *string); - - -/* - * Enumerate the I/O modes supported by gl_get_line(). - */ -typedef enum { - GL_NORMAL_MODE, /* Normal line-at-a-time mode using gl_get_line()'s */ - /* internal event loop. */ - GL_SERVER_MODE /* Non-blocking server mode, driven by an external */ - /* event loop. */ -} GlIOMode; - -/*....................................................................... - * Select the I/O mode to be used by gl_get_line(). - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * mode GlIOMode The I/O mode to establish. Note that - * when server mode, the terminal is placed - * in raw mode, as though gl_raw_io() had - * been called. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_io_mode(GetLine *gl, GlIOMode mode); - -/*....................................................................... - * In server mode, this function configures the terminal for non-blocking - * raw terminal I/O. In normal I/O mode it does nothing. - * - * Callers of this function must be careful to trap all signals that - * terminate or suspend the program, and call gl_normal_io() - * from the corresponding signal handlers in order to restore the - * terminal to its original settings before the program is terminated - * or suspended. They should also trap the SIGCONT signal to detect - * when the program resumes, and ensure that its signal handler - * call gl_raw_io() to redisplay the line and resume editing. - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_raw_io(GetLine *gl); - -/*....................................................................... - * Restore the terminal to the state that it had when gl_raw_io() was - * last called. After calling gl_raw_io(), this function must be called - * before terminating or suspending the program, and before attempting - * other uses of the terminal from within the program. See gl_raw_io() - * for more details. - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_normal_io(GetLine *gl); - -/*....................................................................... - * When in non-blocking server mode, this function can be used to abandon - * the current incompletely entered input line, and prepare to start - * editing a new line on the next call to gl_get_line(). - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -void gl_abandon_line(GetLine *gl); - -/* - * Enumerators of the following type are used to report why - * gl_get_line() returned. This is most useful in non-blocking - * server mode, since in that mode a NULL return value can mean - * either that an error occurred, or that I/O blocked. - */ -typedef enum { - GLR_NEWLINE, /* A new input line was returned */ - GLR_BLOCKED, /* The terminal was in non-blocking mode, and input */ - /* or output would have blocked. */ - GLR_SIGNAL, /* A signal caused gl_get_line() to return. */ - GLR_TIMEOUT, /* An application timeout callback returned GLTO_ABORT */ - GLR_FDABORT, /* An application I/O callack returned GLFD_ABORT */ - GLR_EOF, /* End of file reached */ - GLR_ERROR /* An unexpected error caused gl_get_line() to abort */ -} GlReturnStatus; - -/*....................................................................... - * Ask gl_get_line() what caused it to return. - * - * Input: - * gl GetLine * The line editor resource object. - * Output: - * return GlReturnStatus The return status of the last call to - * gl_get_line(). - */ -GlReturnStatus gl_return_status(GetLine *gl); - -/* - * Enumerate the types of I/O that gl_get_line() can be waiting for - * in non-blocking sedrver I/O mode. - */ -typedef enum { - GLP_READ, /* gl_get_line() is waiting to write to the terminal */ - GLP_WRITE /* gl_get_line() is waiting to read from the terminal */ -} GlPendingIO; - -/*....................................................................... - * In non-blocking server-I/O mode, this function should be called - * from the application's external event loop to see what type of - * terminal I/O is being waited for by gl_get_line(), and thus what - * direction of I/O to wait for with select() or poll(). - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return GlPendingIO The type of pending I/O being waited for. - */ -GlPendingIO gl_pending_io(GetLine *gl); - -/* - * The following enumerators are returned by externally defined action - * functions to tell gl_get_line() how to procede after the action - * function returns. - */ -typedef enum { - GLA_ABORT, /* Cause gl_get_line() to return NULL */ - GLA_RETURN, /* Return the line as though the user had pressed the */ - /* return key. */ - GLA_CONTINUE /* Resume command-line editing */ -} GlAfterAction; - -/*....................................................................... - * Functions of the following form implement external - * application-specific action functions, which can then be bound to - * sequences of terminal keys. - * - * Input: - * gl GetLine * The line editor resource object. - * data void * The anonymous 'data' argument that was - * passed to gl_external_action() when the - * callback function was registered. - * count int A positive repeat count specified by the user, - * or 1 if not specified. Action functions should - * ignore this if repeating the action multiple - * times isn't appropriate. Alternatively they - * can interpret it as a general numeric - * argument. - * curpos size_t The position of the cursor within the input - * line, expressed as the index of the - * corresponding character within the line[] - * array. - * line const char * A read-only copy of the current input line. - * Output - * return GlAfterAction What should gl_get_line() do when the action - * function returns? - * GLA_ABORT - Cause gl_get_line() to - * abort with an error (set - * errno if you need it). - * GLA_RETURN - Return the input line as - * though the user had typed - * the return key. - * GLA_CONTINUE - Resume waiting for keyboard - * input. - */ -#define GL_ACTION_FN(fn) GlAfterAction (fn)(GetLine *gl, void *data, \ - int count, size_t curpos, const char *line) - -typedef GL_ACTION_FN(GlActionFn); - -/*....................................................................... - * Register an application-provided function as an action function. - * This should preferably be called before the first call to gl_get_line() - * so that the name of the action becomes defined before the user's - * configuration file is read. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * data void * Arbitrary application-specific callback - * data to be passed to the callback - * function, fn(). - * fn GlActionFn * The application-specific function that - * implements the action. This will be invoked - * whenever the user presses any - * key-sequence which is bound to this action. - * name const char * The name with which users can refer to the - * binding in tecla configuration files. - * keyseq const char * The key sequence with which to invoke - * the binding. This should be specified in the - * same manner as key-sequences in tecla - * configuration files (eg. "M-^I"). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_register_action(GetLine *gl, void *data, GlActionFn *fn, - const char *name, const char *keyseq); - -/*....................................................................... - * 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_complete_word(). - */ -CplMatches *cpl_complete_word(WordCompletion *cpl, const char *line, - int word_end, void *data, - CplMatchFn *match_fn); - -/*....................................................................... - * Recall the return value of the last call to cpl_complete_word(). - * - * Input: - * cpl WordCompletion * The completion resource object. - * Output: - * return CplMatches * The container of the array of possible - * completions, as returned by the last call to - * cpl_complete_word(). The returned pointer refers - * to a container owned by the parent WordCompletion - * object, and its contents thus potentially - * change on every call to cpl_complete_word(). - * On error, either in the execution of this - * function, or in the last call to - * cpl_complete_word(), NULL is returned, and a - * description of the error can be acquired by - * calling cpl_last_error(cpl). - */ -CplMatches *cpl_recall_matches(WordCompletion *cpl); - -/*....................................................................... - * 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.6.1/libtecla.map b/libtecla-1.6.1/libtecla.map deleted file mode 100644 index a63378e..0000000 --- a/libtecla-1.6.1/libtecla.map +++ /dev/null @@ -1,155 +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; - -tecla_l.5 { - global: - gl_inactivity_timeout; - gl_completion_action; - gl_register_action; - gl_display_text; - gl_error_message; - gl_return_status; - gl_set_term_size; - gl_list_signals; - gl_catch_blocked; - gl_io_mode; - gl_raw_io; - gl_normal_io; - gl_tty_signals; - gl_abandon_line; - gl_handle_signal; - gl_pending_io; - gl_bind_keyseq; - cpl_recall_matches; - gl_erase_terminal; -} tecla_1.4; - -tecla_1.6 { - global: - gl_append_history; - gl_automatic_history; - gl_query_char; - gl_read_char; -} tecla_l.5; diff --git a/libtecla-1.6.1/man/file/teclarc.in b/libtecla-1.6.1/man/file/teclarc.in deleted file mode 100644 index b5ee705..0000000 --- a/libtecla-1.6.1/man/file/teclarc.in +++ /dev/null @@ -1 +0,0 @@ -.so @MISC_MANDIR@/tecla.@MISC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cfc_file_start.in b/libtecla-1.6.1/man/func/cfc_file_start.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cfc_file_start.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cfc_literal_escapes.in b/libtecla-1.6.1/man/func/cfc_literal_escapes.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cfc_literal_escapes.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cfc_set_check_fn.in b/libtecla-1.6.1/man/func/cfc_set_check_fn.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cfc_set_check_fn.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cpl_add_completion.in b/libtecla-1.6.1/man/func/cpl_add_completion.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cpl_add_completion.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cpl_complete_word.in b/libtecla-1.6.1/man/func/cpl_complete_word.in deleted file mode 100644 index d5331e9..0000000 --- a/libtecla-1.6.1/man/func/cpl_complete_word.in +++ /dev/null @@ -1,441 +0,0 @@ -.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 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 @FUNC_MANEXT@ -.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_recall_matches, 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); - -CplMatches *cpl_recall_matches(WordCompletion *cpl); - -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); - - -#define CPL_CHECK_FN(fn) int (fn)(void *data, \\ - const char *pathname) - -typedef CPL_CHECK_FN(CplCheckFn); - -CPL_CHECK_FN(cpl_check_exe); - -CplFileConf *new_CplFileConf(void); - -CplFileConf *del_CplFileConf(CplFileConf *cfc); - -void cfc_literal_escapes(CplFileConf *cfc, int literal); - -void cfc_file_start(CplFileConf *cfc, int start_index); - -void cfc_set_check_fn(CplFileConf *cfc, CplCheckFn *chk_fn, - void *chk_data); - -.fi - -.SH DESCRIPTION - -The \f3cpl_complete_word()\f1 function is part of the tecla library -(see the libtecla(@LIBR_MANEXT@) man page). It is usually called behind the scenes -by \f3gl_get_line(@FUNC_MANEXT@)\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 - WordCompletion *new_WordCompletion(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 - WordCompletion *del_WordCompletion(WordCompletion *cpl) -.fi -.sp -This function deletes the resources that were returned by a previous -call to \f3new_WordCompletion()\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(@FUNC_MANEXT@)\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_WordCompletion()\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 - CplMatches *cpl_recall_matches(WordCompletion *cpl); -.fi -.sp -As a convenience, the return value of the last call to -\f3cpl_complete_word()\f1 can be recalled at a later time by calling -\f3cpl_recall_matches()\f1. If \f3cpl_complete_word()\f1 returned -\f3NULL\f1, so will \f3cpl_recall_matches()\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(@FUNC_MANEXT@)\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 - -.nf -libtecla(@LIBR_MANEXT@), gl_get_line(@FUNC_MANEXT@), ef_expand_file(@FUNC_MANEXT@), -pca_lookup_file(@FUNC_MANEXT@) -.fi - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/man/func/cpl_file_completions.in b/libtecla-1.6.1/man/func/cpl_file_completions.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cpl_file_completions.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cpl_last_error.in b/libtecla-1.6.1/man/func/cpl_last_error.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cpl_last_error.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cpl_list_completions.in b/libtecla-1.6.1/man/func/cpl_list_completions.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cpl_list_completions.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cpl_recall_matches.in b/libtecla-1.6.1/man/func/cpl_recall_matches.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cpl_recall_matches.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/cpl_record_error.in b/libtecla-1.6.1/man/func/cpl_record_error.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/cpl_record_error.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/del_CplFileConf.in b/libtecla-1.6.1/man/func/del_CplFileConf.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/del_CplFileConf.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/del_ExpandFile.in b/libtecla-1.6.1/man/func/del_ExpandFile.in deleted file mode 100644 index 3d0a884..0000000 --- a/libtecla-1.6.1/man/func/del_ExpandFile.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/ef_expand_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/del_GetLine.in b/libtecla-1.6.1/man/func/del_GetLine.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/del_GetLine.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/del_PathCache.in b/libtecla-1.6.1/man/func/del_PathCache.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/del_PathCache.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/del_PcaPathConf.in b/libtecla-1.6.1/man/func/del_PcaPathConf.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/del_PcaPathConf.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/del_WordCompletion.in b/libtecla-1.6.1/man/func/del_WordCompletion.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/del_WordCompletion.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/ef_expand_file.in b/libtecla-1.6.1/man/func/ef_expand_file.in deleted file mode 100644 index f23f3eb..0000000 --- a/libtecla-1.6.1/man/func/ef_expand_file.in +++ /dev/null @@ -1,248 +0,0 @@ -.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 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 @FUNC_MANEXT@ -.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(@LIBR_MANEXT@) 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 -.nf -libtecla(@LIBR_MANEXT@), gl_get_line(@FUNC_MANEXT@), cpl_complete_word(@FUNC_MANEXT@), -pca_lookup_file(@FUNC_MANEXT@) -.fi - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/man/func/ef_last_error.in b/libtecla-1.6.1/man/func/ef_last_error.in deleted file mode 100644 index 3d0a884..0000000 --- a/libtecla-1.6.1/man/func/ef_last_error.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/ef_expand_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/ef_list_expansions.in b/libtecla-1.6.1/man/func/ef_list_expansions.in deleted file mode 100644 index 3d0a884..0000000 --- a/libtecla-1.6.1/man/func/ef_list_expansions.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/ef_expand_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_abandon_line.in b/libtecla-1.6.1/man/func/gl_abandon_line.in deleted file mode 100644 index 24798bc..0000000 --- a/libtecla-1.6.1/man/func/gl_abandon_line.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_io_mode.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_bind_keyseq.in b/libtecla-1.6.1/man/func/gl_bind_keyseq.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_bind_keyseq.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_catch_blocked.in b/libtecla-1.6.1/man/func/gl_catch_blocked.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_catch_blocked.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_change_terminal.in b/libtecla-1.6.1/man/func/gl_change_terminal.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_change_terminal.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_clear_history.in b/libtecla-1.6.1/man/func/gl_clear_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_clear_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_completion_action.in b/libtecla-1.6.1/man/func/gl_completion_action.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_completion_action.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_configure_getline.in b/libtecla-1.6.1/man/func/gl_configure_getline.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_configure_getline.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_customize_completion.in b/libtecla-1.6.1/man/func/gl_customize_completion.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_customize_completion.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_display_text.in b/libtecla-1.6.1/man/func/gl_display_text.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_display_text.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_echo_mode.in b/libtecla-1.6.1/man/func/gl_echo_mode.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_echo_mode.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_erase_terminal.in b/libtecla-1.6.1/man/func/gl_erase_terminal.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_erase_terminal.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_error_message.in b/libtecla-1.6.1/man/func/gl_error_message.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_error_message.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_get_line.in b/libtecla-1.6.1/man/func/gl_get_line.in deleted file mode 100644 index 1995108..0000000 --- a/libtecla-1.6.1/man/func/gl_get_line.in +++ /dev/null @@ -1,2236 +0,0 @@ -.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 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 @FUNC_MANEXT@ -.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_inactivity_timeout, gl_terminal_size, gl_set_term_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, gl_completion_action, gl_display_text, -gl_return_status, gl_error_message, gl_catch_blocked, gl_list_signals, -gl_bind_keyseq, gl_erase_terminal, gl_automatic_history, gl_append_history, -gl_query_char, gl_read_char \- 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_query_char(GetLine *gl, const char *prompt, - char defchar); - -int gl_read_char(GetLine *gl); - -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_bind_keyseq(GetLine *gl, GlKeyOrigin origin, - const char *keyseq, const char *action); - -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_inactivity_timeout(GetLine *gl, GlTimeoutFn *callback, - void *data, unsigned long sec, - unsigned long nsec); - -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_set_term_size(GetLine *gl, int ncolumn, int 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(GetLine *gl); - -int gl_completion_action(GetLine *gl, - void *data, CplMatchFn *match_fn, - int list_only, const char *name, - const char *keyseq); - -int gl_register_action(GetLine *gl, void *data, - GlActionFn *fn, const char *name, - const char *keyseq); - -int gl_display_text(GetLine *gl, int indentation, - const char *prefix, - const char *suffix, int fill_char, - int def_width, int start, - const char *string); - -GlReturnStatus gl_return_status(GetLine *gl); - -const char *gl_error_message(GetLine *gl, char *buff, - size_t n); - -void gl_catch_blocked(GetLine *gl); - -int gl_list_signals(GetLine *gl, sigset_t *set); - -int gl_append_history(GetLine *gl, const char *line); - -int gl_automatic_history(GetLine *gl, int enable); - -.fi - -.SH DESCRIPTION - -The \f3gl_get_line()\f1 function is part of the tecla library (see the -\f3libtecla(@LIBR_MANEXT@)\f1 man page). If the user is typing at a terminal, each -call 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. Documentation of both the -user-level command-line editing features and all user configuration -options, can be found in the \f3tecla(@MISC_MANEXT@)\f1 man page. This man page -concerns itself with documentation for programmers interested in using -this library in their application. -.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. Note that the line pointer returned by one call to -\f3gl_get_line()\f1 can be passed back to the next call to -\f3gl_get_line()\f1 via the \f3start_line\f1. This allows the -application to take the last entered line, and if it contains an -error, to then present it back to the user for re-editing, with the -cursor initially positioned where the error was encountered. - -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 THE RETURN STATUS OF GL_GET_LINE - -As described above, the \f3gl_get_line()\f1 function has two possible -return values; a pointer to the completed input line, or -\f3NULL\f1. Extra information about what caused \f3gl_get_line()\f1 to -return is available both by inspecting \f3errno\f1, and by calling the -\f3gl_return_status()\f1 function. - -.sp -.nf - GlReturnStatus gl_return_status(GetLine *gl); -.fi -.sp - -The following are the possible enumerated values that this -function returns. - -.sp -.nf - GLR_NEWLINE - The last call to \f3gl_get_line()\f1 - successfully returned a completed - input line. - - GLR_BLOCKED - \f3gl_get_line()\f1 was in non-blocking - server mode, and returned early to - avoid blocking the process while - waiting for terminal I/O. The - \f3gl_pending_io()\f1 function can be - used to see what type of I/O - \f3gl_get_line()\f1 was waiting for. - (see the \f3gl_io_mode(@FUNC_MANEXT@)\f1 man page - for details). - - GLR_SIGNAL - A signal was caught by - \f3gl_get_line()\f1 that had an - after-signal disposition of - \f3GLS_ABORT\f1 (See \f3gl_trap_signal()\f1). - - GLR_TIMEOUT - The inactivity timer expired while - \f3gl_get_line()\f1 was waiting for - input, and the timeout callback - function returned \f3GLTO_ABORT\f1. - See \f3gl_inactivity_timeout()\f1 for - information about timeouts. - - GLR_FDABORT - An application I/O callack returned - \f3GLFD_ABORT\f1 (see \f3gl_watch_fd()\f1). - - GLR_EOF - End of file reached. This can happen - when input is coming from a file or a - pipe, instead of the terminal. It also - occurs if the user invokes the - \f3list-or-eof\f1 or \f3del-char-or-list-or-eof\f1 - actions at the start of a new line. - - GLR_ERROR - An unexpected error caused - \f3gl_get_line()\f1 to abort (consult - \f3errno\f1 and/or - \f3gl_error_message()\f1 for details. -.fi -.sp - -When \f3gl_return_status()\f1 returns \f3GLR_ERROR\f1, and the -value of \f3errno\f1 isn't sufficient to explain what -happened, you can use the \f3gl_error_message()\f1 function -to request a description of the last error that occurred. - -.sp -.nf - const char *gl_error_message(GetLine *gl, char *buff, - size_t n); -.fi -.sp - -The return value is a pointer to the message that -occurred. If the \f3buff\f1 argument is \f3NULL\f1, this -will be a pointer to a buffer within \f3gl\f1, who's value -will probably change on the next call to any function -associated with \f3gl_get_line()\f1. Otherwise, if a -non-\f3NULL\f1 \f3buff\f1 argument is provided, the error -message, including a \f3'\\0'\f1 terminator, will be written -within the first \f3n\f1 elements of this buffer, and the -return value will be a pointer to the first element of this -buffer. If the message won't fit in the provided buffer, it -will be truncated to fit. - -.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 - -.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, - -.sp -.nf - gl_configure_getline(gl, "edit-mode vi \\n nobeep", - "/usr/share/myapp/teclarc", - "~/.teclarc"); -.fi -.sp - -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. -.sp -Individual key sequences can also be bound and unbound using the -\f3gl_bind_keyseq()\f1 function. - -.sp -.nf - int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, - const char *keyseq, - const char *action); -.fi -.sp - -The \f3origin\f1 argument specifies the priority of the binding, -according to who it is being established for, and must be one of -the following two values. -.sp -.nf - GL_USER_KEY - The user requested this key-binding. - GL_APP_KEY - This is a default binding set by the - application. -.fi -.sp -When both user and application bindings for a given key-sequence have -been specified, the user binding takes precedence. The application's -binding is subsequently reinstated if the user's binding is later -unbound via either another to this function, or a call to -\f3gl_configure_getline()\f1. - -The \f3keyseq\f1 argument specifies the key-sequence to be bound or -unbound, and is expressed in the same way as in a \f3~/.teclarc\f1 -configuration file. The \f3action\f1 argument must either be a string -containing the name of the action to bind the key-sequence to, or it -must be \f3NULL\f1 or "" to unbind the key-sequence. - -.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(@FUNC_MANEXT@)\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(@FUNC_MANEXT@)\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. -.sp - -If, for some reason, your callback function needs to write something -to the terminal, it must call \f3gl_normal_io()\f1 before doing -so. This will start a new line after the input line that is currently -being edited, reinstate normal terminal I/O, and tell -\f3gl_get_line()\f1 that the input line will need to be redrawn when -the callback returns. - -.SH ADDING COMPLETION ACTIONS - -In the previous section the ability to customize the behavior of the -only default completion action, \f3complete-word\f1, was described. -In this section the ability to install additional action functions, so -that different types of word completion can be bound to different -key-sequences, is described. This is achieved by using the -\f3gl_completion_action()\f1 function. - -.sp -.nf - int gl_completion_action(GetLine *gl, - void *data, CplMatchFn *match_fn, - int list_only, const char *name, - const char *keyseq); -.fi -.sp - -The \f3data\f1 and \f3match_fn\f1 arguments are as described -in the \f3cpl_complete_word\f1 man page, and specify the -callback function that should be invoked to identify -possible completions. The \f3list_only\f1 argument -determines whether the action that is being defined should -attempt to complete the word as far as possible in the input -line before displaying any possible ambiguous completions, -or whether it should simply display the list of possible -completions without touching the input line. The former -option is selected by specifying a value of \f30\f1, and the -latter by specifying a value of \f31\f1. The \f3name\f1 -argument specifies the name by which configuration files and -future invokations of this function should refer to the -action. This must either be the name of an existing -completion action to be changed, or be a new unused name for -a new action. Finally, the \f3keyseq\f1 argument specifies -the default key-sequence to bind the action to. If this is -\f3NULL\f1, no new keysequence will be bound to the action. - -Beware that in order for the user to be able to change the -key-sequence that is bound to actions that are installed in -this manner, when you call \f3gl_completion_action()\f1 to -install a given action for the first time, you should do -this between calling \f3new_GetLine()\f1 and the first call -to \f3gl_get_line()\f1. Otherwise, when the user's -configuration file is read on the first call to -\f3gl_get_line()\f1, the name of the your additional action -won't be known, and any reference to it in the configuration -file will generate an error. - -As discussed for \f3gl_customize_completion()\f1, if your callback -function, for some reason, needs to write anything to the terminal, it -must call \f3gl_normal_io()\f1 before doing so. - -.SH DEFINING CUSTOM ACTIONS - -Although the built-in key-binding actions are sufficient for the needs -of most applications, occasionally a specialized application may need -to define one or more custom actions, bound to application-specific -key-sequences. For example, a sales application would benefit from -having a key-sequence that displayed the part name that corresponded -to a part number preceding the cursor. Such a feature is clearly -beyond the scope of the built-in action functions. So for such special -cases, the \f3gl_register_action()\f1 function is provided. - -.sp -.nf - int gl_register_action(GetLine *gl, void *data, - GlActionFn *fn, const char *name, - const char *keyseq); -.fi -.sp - -This function lets the application register an external function, -\f3fn\f1, that will thereafter be called whenever either the specified -key-sequence, \f3keyseq\f1, is entered by the user, or the user enters -any other key-sequence that the user subsequently binds to the -specified action name, \f3name\f1, in their configuration file. The -\f3data\f1 argument can be a pointer to anything that the application -wishes to have passed to the action function, \f3fn\f1, whenever that -function is invoked. - -The action function, \f3fn\f1, should be declared using the following -macro, which is defined in \f3libtecla.h\f1. - -.sp -.nf - #define GL_ACTION_FN(fn) GlAfterAction (fn)(GetLine *gl, \\ - void *data, int count, size_t curpos, \\ - const char *line) -.fi -.sp - -The \f3gl\f1 and \f3data\f1 arguments are those that were previously -passed to \f3gl_register_action()\f1 when the action function was -registered. The \f3count\f1 argument is a numeric argument which the -user has the option of entering using the \f3digit-argument\f1 action, -before invoking the action. If the user doesn't enter a number, then -the \f3count\f1 argument is set to 1. Nominally this argument is -interpreted as a repeat count, meaning that the action should be -repeated that many times. In practice however, for some actions a -repeat count makes little sense. In such cases, actions can either -simply ignore the \f3count\f1 argument, or use its value for a -different purpose. - -A copy of the current input line is passed in the read-only \f3line\f1 -argument. The current cursor position within this string is given by -the index contained in the \f3curpos\f1 argument. Note that direct -manipulation of the input line and the cursor position is not -permitted. This is because the rules dicated by various modes, such as -vi mode versus emacs mode, no-echo mode, and insert mode versus -overstrike mode etc, make it too complex for an application writer to -write a conforming editing action, as well as constrain future changes -to the internals of \f3gl_get_line()\f1. A potential solution to this -dilema would be to allow the action function to edit the line using -the existing editing actions. This is currently under consideration. - -If the action function wishes to write text to the terminal, without -this getting mixed up with the displayed text of the input line, or -read from the terminal without having to handle raw terminal I/O, then -before doing either of these operations, it must temporarily suspend -line editing by calling the \f3gl_normal_io()\f1 function. This -function flushes any pending output to the terminal, moves the cursor -to the start of the line that follows the last terminal line of the -input line, then restores the terminal to a state that is suitable for -use with the C stdio facilities. The latter includes such things as -restoring the normal mapping of \f3\\n\f1 to \f3\\r\\n\f1, and, when -in server mode, restoring the normal blocking form of terminal -I/O. Having called this function, the action function can read from -and write to the terminal without the fear of creating a mess. It -isn't necessary for the action function to restore the original -editing environment before it returns. This is done automatically by -\f3gl_get_line()\f1 after the action function returns. The following -is a simple example of an action function which writes the sentence -"Hello world" on a new terminal line after the line being edited. When -this function returns, the input line is redrawn on the line that -follows the "Hello world" line, and line editing resumes. - -.sp -.nf - static GL_ACTION_FN(say_hello_fn) - { - if(gl_normal_io(gl)) /* Temporarily suspend editing */ - return GLA_ABORT; - printf("Hello world\\n"); - return GLA_CONTINUE; - } -.fi -.sp - -Action functions must return one of the following values, to tell -\f3gl_get_line()\f1 how to procede. - -.sp -.nf - GLA_ABORT - Cause gl_get_line() to return NULL. - GLA_RETURN - Cause gl_get_line() to return the - completed input line. - GLA_CONTINUE - Resume command-line editing. -.fi -.sp - -Note that the \f3name\f1 argument of \f3gl_register_action()\f1 -specifies the name by which a user can refer to the action in their -configuration file. This allows them to re-bind the action to an -alternate key-seqeunce. In order for this to work, it is necessary to -call \f3gl_register_action()\f1 between calling \f3new_GetLine()\f1 -and the first call to \f3gl_get_line()\f1. - -.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 MANUAL HISTORY ARCHIVAL - -By default, whenever a line is entered by the user, it is -automatically appended to the history list, just before -\f3gl_get_line()\f1 returns the line to the caller. This is convenient -for the majority of applications, but there are also applications that -need finer grained control over what gets added to the history -list. In such cases, the automatic addition of entered lines to the -history list can be turned off by calling the -\f3gl_automatic_history()\f1 function. - -.sp -.nf - int gl_automatic_history(GetLine *gl, int enable); -.fi -.sp - -If this function is called with its \f3enable\f1 argument set to -\f30\f1, \f3gl_get_line()\f1 won't automatically archive subsequently -entered lines. Automatic archiving can be reenabled at a later time, -by calling this function again, with its \f3enable\f1 argument set to -1. While automatic history archiving is disabled, the calling -application can use the \f3gl_append_history()\f1 to append lines to -the history list as needed. - -.sp -.nf - int gl_append_history(GetLine *gl, const char *line); -.fi -.sp - -The \f3line\f1 argument specifies the line to be added to the history -list. This must be a normal \f3'\0'\f1 terminated string. If this -string contains any newline characters, the line that gets archived in -the history list will be terminated by the first of these. Otherwise -it will be terminated by the \f3'\0'\f1 terminator. If the line is -longer than the maximum input line length, that was specified when -\f3new_GetLine()\f1 was called, when the line is recalled, it will get -truncated to the actual \f3gl_get_line()\f1 line length. - -If successful, \f3gl_append_history()\f1 returns 0. Otherwise it -returns non-zero, and sets \f3errno\f1 to one of the following values. - -.sp -.nf - EINVAL - One of the arguments passed to - gl_append_history() was NULL. - ENOMEM - The specified line was longer than the allocated - size of the history buffer (as specified when - new_GetLine() was called), so it couldn't be - archived. -.fi -.sp - -A textual description of the error can optionally be obtained by -calling \f3gl_error_message()\f1. Note that after such an error, the -history list remains in a valid state to receive new history lines, so -there is little harm in simply ignoring the return status of -\f3gl_append_history()\f1. - -.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 - -By default, \f3gl_get_line()\f1 doesn't return until either a complete -input line has been entered by the user, or an error occurs. In -programs that need to watch for I/O from other sources than the -terminal, there are two options. - -.sp -.nf - 1. Use the functions described in the - \f3gl_io_mode(@FUNC_MANEXT@)\f1 man page to switch - \f3gl_get_line()\f1 into non-blocking server mode. In this mode, - \f3gl_get_line()\f1 becomes a non-blocking, incremental - line-editing function that can safely be called from - an external event loop. Although this is a very - versatile method, it involves taking on some - responsibilities that are normally performed behind - the scenes by \f3gl_get_line()\f1. - - 2. 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. -.fi -.sp - -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. When this - happens, \f3gl_get_line()\f1 returns - \f3NULL\f1, and a following call to - \f3gl_return_status()\f1 will return - \f3GLR_FDABORT\f1. Note that if the - application needs \f3errno\f1 always to - have a meaningful value when - \f3gl_get_line()\f1 returns \f3NULL\f1, - the callback function should set - \f3errno\f1 appropriately. - 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 - -If the callback function needs to read or write to the terminal, it -should ideally first call \f3gl_normal_io(gl)\f1 to temporarily -suspend line editing. This will restore the terminal to canonical, -blocking-I/O, mode, and move the cursor to the start of a new terminal -line. Later, when the callback returns, \f3gl_get_line()\f1 will -notice that \f3gl_normal_io()\f1 was called, redisplay the input line -and resume editing. Note that in this case the return values, -\f3GLFD_REFRESH\f1 and \f3GLFD_CONTINUE\f1 are equivalent. - -.sp - -To support cases where the callback function calls a third-party -function which occasionally and unpredictably writes to the terminal, -the automatic conversion of \f3"\n"\f1 to \f3"\r\n"\f1 is re-enabled -before the callback function is called. If the callack knows that the -third-party function wrote to the terminal, it should then return the -\f3GLFD_REFRESH\f1 return value, to tell \f3gl_get_line()\f1 to -redisplay the input line. - -.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 SETTING AN INACTIVITY TIMEOUT - -On systems with the \f3select()\f1 system call, the -\f3gl_inactivity_timeout()\f1 function can be used to set or cancel an -inactivity timeout. Inactivity in this case refers both to keyboard -input, and to I/O on any file descriptors registered by prior and -subsequent calls to \f3gl_watch_fd()\f1. On oddball systems that don't -have \f3select()\f1, this call has no effect. - -.sp -.nf - int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *callback, - void *data, unsigned long sec, - unsigned long nsec); -.fi -.sp - -The timeout is specified in the form of an integral number of seconds -and an integral number of nanoseconds, via the \f3sec\f1 and -\f3nsec\f1 arguments respectively. Subsequently, whenever no activity -is seen for this time period, the function specified via the -\f3callback\f1 argument is called. The \f3data\f1 argument of -\f3gl_inactivity_timeout()\f1 is passed verbatim to this callback function -whenever it is invoked, and can thus be used to pass arbitrary -application-specific information to the callback. The following macro -is provided in \f3libtecla.h\f1 for applications to use to declare and -prototype timeout callback functions. - -.sp -.nf - #define GL_TIMEOUT_FN(fn) \\ - GlAfterTimeout (fn)(GetLine *gl, void *data) -.fi -.sp - -On returning, the application's callback is expected to return one of -the following enumerators to tell \f3gl_get_line()\f1 how to procede -after the timeout has been handled by the callback. - -.sp -.nf - GLTO_ABORT - Tell gl_get_line() to abort. When - this happens, \f3gl_get_line()\f1 will - return \f3NULL\f1, and a following call - to \f3gl_return_status()\f1 will return - \f3GLR_TIMEOUT\f1. Note that if the - application needs \f3errno\f1 always to - have a meaningful value when - \f3gl_get_line()\f1 returns \f3NULL\f1, - the callback function should set - \f3errno\f1 appropriately. - GLTO_REFRESH - Redraw the input line, then continue - waiting for input. You should return - this value if your callback wrote to the - terminal without having first called - \f3gl_normal_io(gl)\f1. - GLTO_CONTINUE - In normal blocking-I/O mode, continue to - wait for input, without redrawing the - user's input line. - In non-blocking server I/O mode (see - gl_io_mode(@FUNC_MANEXT@)), cause \f3gl_get_line()\f1 - to act as though I/O blocked. This means - that \f3gl_get_line()\f1 will immediately - return \f3NULL\f1, and a following call - to \f3gl_return_status()\f1 will return - \f3GLR_BLOCKED\f1. -.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 - -If the callback function needs to read or write to the terminal, it -should ideally first call \f3gl_normal_io(gl)\f1 to temporarily -suspend line editing. This will restore the terminal to canonical, -blocking-I/O, mode, and move the cursor to the start of a new terminal -line. Later, when the callback returns, \f3gl_get_line()\f1 will -notice that \f3gl_normal_io()\f1 was called, redisplay the input line -and resume editing. Note that in this case the return values, -\f3GLTO_REFRESH\f1 and \f3GLTO_CONTINUE\f1 are equivalent. - -.sp - -To support cases where the callback function calls a third-party -function which occasionally and unpredictably writes to the terminal, -the automatic conversion of \f3"\n"\f1 to \f3"\r\n"\f1 is re-enabled -before the callback function is called. If the callack knows that the -third-party function wrote to the terminal, it should then return the -\f3GLTO_REFRESH\f1 return value, to tell \f3gl_get_line()\f1 to -redisplay the input line. - -.sp - -Note that although the timeout argument includes a nano-second -component, few computer clocks presently have resolutions that are -finer than a few milliseconds, so asking for less than a few -milliseconds is equivalent to requesting zero seconds on a lot of -systems. If this would be a problem, you should base your timeout -selection on the actual resolution of the host clock (eg. by calling -\f3sysconf(_SC_CLK_TCK)\f1). - -.sp - -To turn off timeouts, simply call \f3gl_inactivity_timeout()\f1 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 \f3gl_get_line()\f1 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. - - SIGPOLL - On SVR4 systems, this signal notifies the - process of an asynchronous I/O event. Note - that under 4.3+BSD, SIGIO and SIGPOLL are - the same. On other systems, SIGIO is ignored - by default, so \f3gl_get_line()\f1 doesn't - trap it by default. - - 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. - - SIGXFSZ - This signal is generated when a process - exceeds its soft file-size 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 or \f3SIGPOLL\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 overridden 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 \f3gl_get_line()\f1 to abort. When - this happens, \f3gl_get_line()\f1 returns - \f3NULL\f1, and a following call to - \f3gl_return_status()\f1 will return - \f3GLR_SIGNAL\f1. Note that if the - application needs \f3errno\f1 always to - have a meaningful value when - \f3gl_get_line()\f1 returns \f3NULL\f1, - the callback function should set - \f3errno\f1 appropriately. - 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 RELIABLE SIGNAL HANDLING - -Signal handling is suprisingly hard to do reliably without race -conditions. In \f3gl_get_line()\f1 a lot of care has been taken to -allow applications to perform reliable signal handling around -\f3gl_get_line()\f1. This section explains how to make use of this. - -As an example of the problems that can arise if the application isn't -written correctly, imagine that one's application has a SIGINT signal -handler that sets a global flag. Now suppose that the application -tests this flag just before invoking \f3gl_get_line()\f1. If a SIGINT -signal happens to be received in the small window of time between the -statement that tests the value of this flag, and the statement that -calls \f3gl_get_line()\f1, then \f3gl_get_line()\f1 will not see the -signal, and will not be interrupted. As a result, the application -won't be able to respond to the signal until the user gets around to -finishing entering the input line and \f3gl_get_line()\f1 -returns. Depending on the application, this might or might not be a -disaster, but at the very least it would puzzle the user. - -The way to avoid such problems is to do the following. - -1. If needed, use the \f3gl_trap_signal()\f1 function to - configure \f3gl_get_line()\f1 to abort when important - signals are caught. - -2. Configure \f3gl_get_line()\f1 such that if any of the - signals that it catches are blocked when - \f3gl_get_line()\f1 is called, they will be unblocked - automatically during times when \f3gl_get_line()\f1 is - waiting for I/O. This can be done either - on a per signal basis, by calling the - \f3gl_trap_signal()\f1 function, and specifying the - \f3GLS_UNBLOCK\f1 attribute of the signal, or globally by - calling the \f3gl_catch_blocked()\f1 function. - -.sp -.nf - void gl_catch_blocked(GetLine *gl); -.fi -.sp - - This function simply adds the \f3GLS_UNBLOCK\f1 attribute - to all of the signals that it is currently configured to - trap. - -3. Just before calling \f3gl_get_line()\f1, block delivery - of all of the signals that \f3gl_get_line()\f1 is - configured to trap. This can be done using the POSIX - \f3sigprocmask()\f1 function in conjunction with the - \f3gl_list_signals()\f1 function. - -.sp -.nf - int gl_list_signals(GetLine *gl, sigset_t *set); -.fi -.sp - - This function returns the set of signals that it is - currently configured to catch in the \f3set\f1 argument, - which is in the form required by \f3sigprocmask()\f1. - -4. In the example, one would now test the global flag that - the signal handler sets, knowing that there is now no - danger of this flag being set again until - \f3gl_get_line()\f1 unblocks its signals while performing - I/O. - -5. Eventually \f3gl_get_line()\f1 returns, either because - a signal was caught, an error occurred, or the user - finished entering their input line. - -6. Now one would check the global signal flag again, and if - it is set, respond to it, and zero the flag. - -7. Use \f3sigprocmask()\f1 to unblock the signals that were - blocked in step 3. - -The same technique can be used around certain POSIX -signal-aware functions, such as \f3sigsetjmp()\f1 and -\f3sigsuspend()\f1, and in particular, the former of these -two functions can be used in conjunction with -\f3siglongjmp()\f1 to implement race-condition free signal -handling around other long-running system calls. The way to -do this, is explained next, by showing how -\f3gl_get_line()\f1 manages to reliably trap signals around -calls to functions like \f3read()\f1 and \f3select()\f1 -without race conditions. - -The first thing that \f3gl_get_line()\f1 does, whenever it -is called, is to use the POSIX \f3sigprocmask()\f1 function -to block the delivery of all of the signals that it is -currently configured to catch. This is redundant if the -application has already blocked them, but it does no -harm. It undoes this step just before returning. - -Whenever \f3gl_get_line()\f1 needs to call \f3read()\f1 or -\f3select()\f1 to wait for input from the user, it first -calls the POSIX \f3sigsetjmp()\f1 function, being sure to -specify a non-zero value for its \f3savesigs\f1 argument. -The reason for the latter argument will become clear -shortly. - -If \f3sigsetjmp()\f1 returns zero, \f3gl_get_line()\f1 then -does the following. - -.sp -.nf -a. It uses the POSIX \f3sigaction()\f1 function to register - a temporary signal handler to all of the signals that it - is configured to catch. This signal handler does two - things. - - 1. It records the number of the signal that was received - in a file-scope variable. - - 2. It then calls the POSIX \f3siglongjmp()\f1 - function using the buffer that was passed to - \f3sigsetjmp()\f1 for its first argument, and - a non-zero value for its second argument. - - When this signal handler is registered, the \f3sa_mask\f1 - member of the \f3struct sigaction act\f1 argument of the - call to \f3sigaction()\f1 is configured to contain all of - the signals that \f3gl_get_line()\f1 is catching. This - ensures that only one signal will be caught at once by - our signal handler, which in turn ensures that multiple - instances of our signal handler don't tread on each - other's toes. - -b. Now that the signal handler has been set up, - \f3gl_get_line()\f1 unblocks all of the signals that it - is configured to catch. - -c. It then calls the \f3read()\f1 or \f3select()\f1 system - calls to wait for keyboard input. - -d. If this system call returns (ie. no signal is received), - \f3gl_get_line()\f1 blocks delivery of the signals of - interest again. - -e. It then reinstates the signal handlers that were - displaced by the one that was just installed. -.fi -.sp - -Alternatively, if \f3sigsetjmp()\f1 returns non-zero, this -means that one of the signals being trapped was caught while -the above steps were executing. When this happens, -\f3gl_get_line()\f1 does the following. - -First, note that when a call to \f3siglongjmp()\f1 causes -\f3sigsetjmp()\f1 to return, provided that the -\f3savesigs\f1 argument of \f3sigsetjmp()\f1 was non-zero, -as specified above, the signal process mask is restored to -how it was when \f3sigsetjmp()\f1 was called. This is the -important difference between \f3sigsetjmp()\f1 and the older -problematic \f3setjmp()\f1, and is the essential ingredient -that makes it possible to avoid signal handling race -conditions. Because of this we are guaranteed that all of -the signals that we blocked before calling \f3sigsetjmp()\f1 -are blocked again as soon as any signal is caught. The -following statements, which are then executed, are thus -guaranteed to be executed without any further signals being -caught. - -1. If so instructed by the \f3gl_get_line()\f1 configuration - attributes of the signal that was caught, - \f3gl_get_line()\f1 restores the terminal attributes to - the state that they had when \f3gl_get_line()\f1 was - called. This is particularly important for signals that - suspend or terminate the process, since otherwise the - terminal would be left in an unusable state. - -2. It then reinstates the application's signal handlers. - -3. Then it uses the C standard-library \f3raise()\f1 - function to re-send the application the signal that - was caught. - -3. Next it unblocks delivery of the signal that we just - sent. This results in the signal that was just sent - via \f3raise()\f1, being caught by the application's - original signal handler, which can now handle it as it - sees fit. - -4. If the signal handler returns (ie. it doesn't terminate - the process), \f3gl_get_line()\f1 blocks delivery of the - above signal again. - -5. It then undoes any actions performed in the first of the - above steps, and redisplays the line, if the signal - configuration calls for this. - -6. \f3gl_get_line()\f1 then either resumes trying to - read a character, or aborts, depending on the - configuration of the signal that was caught. - -What the above steps do in essence is to take asynchronously -delivered signals and handle them synchronously, one at a -time, at a point in the code where \f3gl_get_line()\f1 has -complete control over its environment. - -.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. -.sp -Even on systems that do support \f3ioctl(TIOCGWINSZ)\f1, if the -terminal is on the other end of a serial line, the terminal driver -generally has no way of detecting when a resize occurs or of querying -what the current size is. In such cases no \f3SIGWINCH\f1 is sent to -the process, and the dimensions returned by \f3ioctl(TIOCGWINSZ)\f1 -aren't correct. The only way to handle such instances is to provide a -way for the user to enter a command that tells the remote system what -the new size is. This command would then call the -\f3gl_set_term_size()\f1 function to tell \f3gl_get_line()\f1 about -the change in size. - -.sp -.nf - int gl_set_term_size(GetLine *gl, int ncolumn, int nline); -.fi -.sp - -The \f3ncolumn\f1 and \f3nline\f1 arguments are used to specify the -new dimensions of the terminal, and must not be less than 1. On -systems that do support \f3ioctl(TIOCGWINSZ)\f1, this function first -calls \f3ioctl(TIOCSWINSZ)\f1 to tell the terminal driver about the -change in size. In non-blocking server-I/O mode, if a line is -currently being input, the input line is then redrawn to accomodate -the changed size. Finally the new values are recorded in \f3gl\f1 for -future use by \f3gl_get_line()\f1. -.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 fallback terminal -dimensions, 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 via \f3ioctl(TIOCGWINSZ)\f1 or -environment variables. - -.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 SINGLE CHARACTER QUERIES - -Using \f3gl_get_line()\f1 to query the user for a single character -reply, is inconvenient for the user, since they must hit the enter or -return key before the character that they typed is returned to the -program. Thus the \f3gl_query_char()\f1 function has been provided for -single character queries like this. - -.sp -.nf - int gl_query_char(GetLine *gl, const char *prompt, - char defchar); -.fi -.sp - -This function displays the specified prompt at the start of a new -line, and waits for the user to type a character. When the user types -a character, \f3gl_query_char()\f1 displays it to the right of the -prompt, starts a newline, then returns the character to the calling -program. The return value of the function is the character that was -typed. If the read had to be aborted for some reason, \f3EOF\f1 is -returned instead. In the latter case, the application can call the -previously documented \f3gl_return_status()\f1, to find out what went -wrong. This could, for example, have been the reception of a signal, -or the optional inactivity timer going off. - -If the user simply hits enter, the value of the \f3defchar\f1 argument -is substituted. This means that when the user hits either newline or -return, the character specified in \f3defchar\f1, is displayed after -the prompt, as though the user had typed it, as well as being returned -to the calling application. If such a replacement is not important, -simply pass \f3'\n'\f1 as the value of \f3defchar\f1. - -If the entered character is an unprintable character, it is displayed -symbolically. For example, control-A is displayed as ^A, and -characters beyond 127 are displayed in octal, preceded by a -backslash. - -As with \f3gl_get_line()\f1, echoing of the entered character can be -disabled using the \f3gl_echo_mode()\f1 function. - -If the calling process is suspended while waiting for the user to type -their response, the cursor is moved to the line following the prompt -line, then when the process resumes, the prompt is redisplayed, and -\f3gl_query_char()\f1 resumes waiting for the user to type a -character. - -Note that in non-blocking server mode, (see -gl_io_mode(@FUNC_MANEXT@)), if an incomplete input line is in the -process of being read when \f3gl_query_char()\f1 is called, the -partial input line is discarded, and erased from the terminal, before -the new prompt is displayed. The next call to \f3gl_get_line()\f1 will -thus start editing a new line. - -.SH READING RAW CHARACTERS - -Whereas the \f3gl_query_char()\f1 function visibly prompts the user -for a character, and displays what they typed, the -\f3gl_read_char()\f1 function reads a signal character from the user, -without writing anything to the terminal, or perturbing any -incompletely entered input line. This means that it can be called not -only from between calls to \f3gl_get_line()\f1, but also from callback -functions that the application has registered to be called by -\f3gl_get_line()\f1. - -.sp -.nf - int gl_read_char(GetLine *gl); -.fi -.sp - -On success, the return value of \f3gl_read_char()\f1 is the character -that was read. On failure, \f3EOF\f1 is returned, and the -\f3gl_return_status()\f1 function can be called to find out what went -wrong. Possibilities include the optional inactivity timer going off, -the receipt of a signal that is configured to abort gl_get_line(), or -terminal I/O blocking, when in non-blocking server-I/O mode. - -Beware that certain keyboard keys, such as function keys, and cursor -keys, usually generate at least 3 characters each, so a single call to -\f3gl_read_char()\f1 won't be enough to identify such keystrokes. - -.SH CLEARING THE TERMINAL - -The calling program can clear the terminal by calling -\f3gl_erase_terminal()\f1. In non-blocking server-I/O mode, this -function also arranges for the current input line to be redrawn from -scratch when \f3gl_get_line()\f1 is next called. - -.sp -.nf - int gl_erase_terminal(GetLine *gl); -.fi -.sp - -.SH DISPLAYING TEXT DYNAMICALLY - -Between calls to \f3gl_get_line()\f1, the \f3gl_display_text()\f1 -function provides a convenient way to display paragraphs of text, -left-justified and split over one or more terminal lines according to -the constraints of the current width of the terminal. Examples of the -use of this function may be found in the demo programs, where it is -used to display introductions. In those examples the advanced use of -optional prefixes, suffixes and filled lines to draw a box around the -text is also illustrated. - -.sp -.nf - int gl_display_text(GetLine *gl, int indentation, - const char *prefix, - const char *suffix, int fill_char, - int def_width, int start, - const char *string); -.fi -.sp -If \f3gl\f1 isn't currently connected to a terminal, for example if -the output of a program that uses \f3gl_get_line()\f1 is being piped -to another program or redirected to a file, then the value of the -\f3def_width\f1 parameter is used as the terminal width. - -The \f3indentation\f1 argument specifies the number of characters to -use to indent each line of ouput. The \f3fill_char\f1 argument -specifies the character that will be used to perform this indentation. - -The \f3prefix\f1 argument can either be \f3NULL\f1, or be a string to -place at the beginning of each new line (after any indentation). -Similarly, the \f3suffix\f1 argument can either be \f3NULL\f1, or be a -string to place at the end of each line. The suffix is placed flush -against the right edge of the terminal, and any space between its -first character and the last word on that line is filled with the -character specified via the \f3fill_char\f1 argument. Normally the -fill-character is a space. - -The \f3start\f1 argument tells \f3gl_display_text()\f1 how many -characters have already been written to the current terminal line, and -thus tells it the starting column index of the cursor. Since the -return value of \f3gl_display_text()\f1 is the ending column index of -the cursor, by passing the return value of one call to the \f3start\f1 -argument of the next call, a paragraph that is broken between more -than one string can be composed by calling \f3gl_display_text()\f1 for -each successive portion of the paragraph. Note that literal newline -characters are necessary at the end of each paragraph to force a new -line to be started. - -On error, \f3gl_display_text()\f1 returns -1. - -.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()\f1 to display a different -prompt when the callback returns. Except in non-blocking -server mode, it has no effect if used between calls to -\f3gl_get_line()\f1. In non-blocking server mode (see the -\f3gl_io_mode(@FUNC_MANEXT@)\f1 man page, when used between two calls to -\f3gl_get_line()\f1 that are operating on the same input -line, the current input line will be re-drawn with the new -prompt on the following call to \f3gl_get_line()\f1. - -.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. Further documentation on how the user can make use -of this to enter international characters can be found in the -\f3tecla(@MISC_MANEXT@)\f1 man page. - -.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 -.nf -libtecla(@LIBR_MANEXT@), gl_io_mode(@FUNC_MANEXT@), tecla(@MISC_MANEXT@), ef_expand_file(@FUNC_MANEXT@), -cpl_complete_word(@FUNC_MANEXT@), pca_lookup_file(@FUNC_MANEXT@) -.fi - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/man/func/gl_group_history.in b/libtecla-1.6.1/man/func/gl_group_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_group_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_handle_signal.in b/libtecla-1.6.1/man/func/gl_handle_signal.in deleted file mode 100644 index 24798bc..0000000 --- a/libtecla-1.6.1/man/func/gl_handle_signal.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_io_mode.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_ignore_signal.in b/libtecla-1.6.1/man/func/gl_ignore_signal.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_ignore_signal.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_inactivity_timeout.in b/libtecla-1.6.1/man/func/gl_inactivity_timeout.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_inactivity_timeout.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_io_mode.in b/libtecla-1.6.1/man/func/gl_io_mode.in deleted file mode 100644 index 5789666..0000000 --- a/libtecla-1.6.1/man/func/gl_io_mode.in +++ /dev/null @@ -1,571 +0,0 @@ -.\" Copyright (c) 2002, 2003, 2004 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_io_mode @FUNC_MANEXT@ -.SH NAME - gl_io_mode, gl_raw_io, gl_normal_io, gl_tty_signals, gl_abandon_line, - gl_handle_signal, gl_pending_io \- How to use gl_get_line() from an external event loop. -.SH SYNOPSIS -.nf -#include <libtecla.h> - -int gl_io_mode(GetLine *gl, GlIOMode mode); - -int gl_raw_io(GetLine *gl); - -int gl_normal_io(GetLine *gl); - -int gl_tty_signals(void (*term_handler)(int), - void (*susp_handler)(int), - void (*cont_handler)(int), - void (*size_handler)(int)); - -void gl_abandon_line(GetLine *gl); - -void gl_handle_signal(int signo, GetLine *gl, int ngl); - -GlPendingIO gl_pending_io(GetLine *gl); - -.fi - -.SH DESCRIPTION - -The \f3gl_get_line()\f1 function, which is documented separately in -the \f3gl_get_line(@FUNC_MANEXT@)\f1 man page, supports two different I/O modes. -These are selected by calling the \f3gl_io_mode()\f1 function. - -.sp -.nf - int gl_io_mode(GetLine *gl, GlIOMode mode); -.fi -.sp - -The \f3mode\f1 argument of this function specifies the new I/O mode, -and must be one of the following. - -.sp -.nf - GL_NORMAL_MODE - Select the normal blocking-I/O mode. - In this mode \f3gl_get_line()\f1 - doesn't return until either an error - occurs of the user finishes entering a - new line. This mode is the focus of - the \f3gl_get_line(@FUNC_MANEXT@)\f1 man page. - - GL_SERVER_MODE - Select non-blocking server I/O mode. - In this mode, since non-blocking - terminal I/O is used, the entry of - each new input line typically requires - many calls to \f3gl_get_line()\f1 from - an external I/O-driven event loop. - This mode is the focus of this man - page. -.fi -.sp - -Newly created \f3GetLine\f1 objects start in normal I/O -mode, so to switch to non-blocking server mode requires an -initial call to \f3gl_io_mode()\f1. - -.SH SERVER I/O MODE - -In non-blocking server I/O mode, the application is required -to have an event loop which calls \f3gl_get_line()\f1 -whenever the terminal file descriptor can do the type I/O -that \f3gl_get_line()\f1 is waiting for. To determine which -type of I/O \f3gl_get_line()\f1 is waiting for, the -application calls the \f3gl_pending_io()\f1 function. - -.sp -.nf - GlPendingIO gl_pending_io(GetLine *gl); -.fi -.sp - -The return value of this function is one of the following two -enumerated values. - -.sp -.nf - GLP_READ - gl_get_line() is waiting to write a - character to the terminal. - - GLP_WRITE - gl_get_line() is waiting to read a - character from the keyboad. -.fi -.sp - -If the application is using either the \f3select()\f1 or \f3poll()\f1 -system calls to watch for I/O on a group of file descriptors, then it -should call the \f3gl_pending_io()\f1 function before each call to -these functions to see which direction of I/O it should tell them to -watch for, and configure their arguments accordingly. In the case of -the \f3select()\f1 system call, this means using the \f3FD_SET()\f1 -macro to add the terminal file descriptor either to the set of file -descriptors to be watched for readability, or the set to be watched -for writability. - -As in normal I/O mode, the return value of \f3gl_get_line()\f1 is -either a pointer to a completed input line, or \f3NULL\f1. However, -whereas in normal I/O mode a \f3NULL\f1 return value always means that -an error occurred, in non-blocking server mode, \f3NULL\f1 is also -returned when \f3gl_get_line()\f1 can't read or write to the terminal -without blocking. Thus in non-blocking server mode, in order to -determine when a \f3NULL\f1 return value signifies that an error -occurred or not, it is necessary to call the \f3gl_return_status()\f1 -function. If this function returns the enumerated value, -\f3GLR_BLOCKED\f1, as documented in the \f3gl_get_line(@FUNC_MANEXT@)\f1 man page, -this means that \f3gl_get_line()\f1 is waiting for I/O, and no error -has occurred. - -When \f3gl_get_line()\f1 returns \f3NULL\f1 and -\f3gl_return_status()\f1 indicates that this is due to blocked -terminal I/O, the application should call \f3gl_get_line()\f1 again -when the type of I/O reported by \f3gl_pending_io()\f1 becomes -possible. The \f3prompt\f1, \f3start_line\f1 and \f3start_pos\f1 -arguments of \f3gl_get_line()\f1 will be ignored on these calls. If -you need to change the prompt of the line that is currently being -edited, then you can call the \f3gl_replace_prompt()\f1 function -(documented in the \f3gl_get_line(@FUNC_MANEXT@) man page) between calls to -\f3gl_get_line()\f1. - -.SH GIVING UP THE TERMINAL - -A complication that is unique to non-blocking server mode is that it -requires that the terminal be left in raw mode between calls to -\f3gl_get_line()\f1. If this weren't the case, the external event loop -wouldn't be able to detect individual key-presses, and the basic line -editing implemented by the terminal driver would clash with the -editing provided by \f3gl_get_line()\f1. What this means is that any -time that the terminal needs to be used for other things than entering -a new input line with \f3gl_get_line()\f1, it needs to be restored to -a usable state. In particular, whenever the process is suspended or -terminated, the terminal must be returned to a normal state. If this -isn't done, then depending on the characteristics of the shell that -was used to invoke the program, the user may end up with a hung -terminal. To this end, the \f3gl_normal_io()\f1 function is provided -for switching the terminal back to the state that it was in when raw -mode was last established. - -.sp -.nf - int gl_normal_io(GetLine *gl); -.fi -.sp - -What this function does is first flush any pending output to the -terminal, then move the cursor to the start of the terminal line which -follows the end of the incompletely entered input line. At this point -it is safe to suspend or terminate the process, and it is safe for the -application to read and write to the terminal. To resume entry of the -input line, the application should call the \f3gl_raw_io()\f1 -function. - -.sp -.nf - int gl_raw_io(GetLine *gl); -.fi -.sp - -This function starts a new line, redisplays the partially completed -input line (if any), restores the cursor position within this line to -where it was when \f3gl_normal_io()\f1 was called, then switches back -to raw, non-blocking terminal mode ready to continue entry of the -input line when \f3gl_get_line()\f1 is next called. - -Note that in non-blocking server mode, if \f3gl_get_line()\f1 is -called after a call to \f3gl_normal_io()\f1, without an intervening -call to \f3gl_raw_io()\f1, \f3gl_get_line()\f1 will call -\f3gl_raw_mode()\f1 itself, and the terminal will remain in this mode -when \f3gl_get_line()\f1 returns. - -.SH SIGNAL HANDLING - -In the previous section it was pointed out that in non-blocking server -mode, the terminal must be restored to a sane state whenever a signal -is received that either suspends or terminates the process. In normal -I/O mode, this is done for you by \f3gl_get_line()\f1, but in -non-blocking server mode, since the terminal is left in raw mode -between calls to \f3gl_get_line()\f1, this signal handling has to be -done by the application. Since there are many signals that can suspend -or terminate a process, as well as other signals that are important to -\f3gl_get_line()\f1, such as the \f3SIGWINCH\f1 signal, which tells it -when the terminal size has changed, the \f3gl_tty_signals()\f1 -function is provided for installing signal handlers for all pertinent -signals. - -.sp -.nf - int gl_tty_signals(void (*term_handler)(int), - void (*susp_handler)(int), - void (*cont_handler)(int), - void (*size_handler)(int)); -.fi -.sp - -What this does is use \f3gl_get_line()\f1's internal list of signals -to assign specified signal handlers to groups of signals. The -arguments of this function are as follows. - -.sp -.nf - term_handler - This is the signal handler that is to be - used to trap signals that by default - terminate any process that receives - them (eg. SIGINT or SIGTERM). - - susp_handler - This is the signal handler that is to be - used to trap signals that by default - suspend any process that receives them, - (eg. SIGTSTP or SIGTTOU). - - cont_handler - This is the signal handler that is to be - used to trap signals that are usually - sent when a process resumes after being - suspended (usually SIGCONT). Beware that there is - nothing to stop a user from sending one of these - signals at other times. - - size_handler - This signal handler is used to trap - signals that are sent to processes when - their controlling terminals are resized - by the user (eg. SIGWINCH). -.fi -.sp - -These arguments can all be the same, if so desired, and you can -specify \f3SIG_IGN\f1 (ignore this signal) or \f3SIG_DFL\f1 (use the -system-provided default signal handler) instead of a function where -pertinent. In particular, it is rarely useful to trap \f3SIGCONT\f1, -so the \f3cont_handler\f1 argument will usually be \f3SIG_DFL\f1 or -\f3SIG_IGN\f1. - -The \f3gl_tty_signals()\f1 function uses the POSIX \f3sigaction()\f1 -function to install these signal handlers, and it is careful to use -the \f3sa_mask\f1 member of each sigaction structure to ensure that -only one of these signals is ever delivered at a time. This guards -against different instances of these signal handlers from -simultaneously trying to write to common global data, such as a shared -\f3sigsetjmp()\f1 buffer or a signal-received flag. - -The signal handlers that are installed by this function, should call -the \f3gl_handle_signal(). - -.sp -.nf - void gl_handle_signal(int signo, GetLine *gl, int ngl); -.fi -.sp - -The \f3signo\f1 argument tells this function which signal it is being -asked to respond to, and the \f3gl\f1 argument should be a pointer to -the first element of an array of \f3ngl\f1 \f3GetLine\f1 objects. If -your application only has one of these objects, just pass its pointer -as the \f3gl\f1 argument and specify \f3ngl\f1 as \f31\f1. - -Depending on the signal that is being handled, this function does -different things. - -.SS Terminal resize signals (SIGWINCH) - -If the signal indicates that the terminal was resized, then it -arranges for the next call to \f3gl_get_line()\f1 to ask the terminal -for its new size and redraw the input line accordingly. In order that -\f3gl_get_line()\f1 be called as soon as possible to do this, -\f3gl_handle_signal()\f1 also arranges that the next call to -\f3gl_pending_io()\f1 will return \f3GLP_WRITE\f1. Thus if the -application waits for I/O in \f3select()\f1 or \f3poll()\f1, then the -application needs to ensure that these functions will be reliably -aborted when a signal is caught and handled by the application. More -on this below. - -.SH Process termination signals. - -If the signal that was caught is one of those that by default -terminates any process that receives it, then \f3gl_handle_signal()\f1 -does the following steps. - -1. First it blocks the delivery of all signals that can be - blocked (ie. \f3SIGKILL\f1 and \f3SIGSTOP\f1 can't be blocked) - -2. Next it calls \f3gl_normal_io()\f1 for each of the \f3ngl\f1 - \f3GetLine\f1 objects. Note that this does nothing to any of the - \f3GetLine\f1 objects that aren't currently in raw mode. - -3. Next it sets the signal handler of the signal to its default, - process-termination disposition. - -4. Next it re-sends the process the signal that was caught. - -5. Finally it unblocks delivery of this signal, which - results in the process being terminated. - -.SH Process suspension signals. - -If the default disposition of the signal is to suspend the process, -the same steps are executed as for process termination signals, except -that when the process is later resumed, \f3gl_handle_signal()\f1 -continues, and does the following steps. - -6. It re-blocks delivery of the signal. - -7. It reinstates the signal handler of the signal to the one - that was displaced when its default disposition was substituted. - -8. For any of the \f3GetLine\f1 objects that were in raw mode when - \f3gl_handle_signal()\f1 was called, \f3gl_handle_signal()\f1 then - calls \f3gl_raw_io()\f1, to resume entry of the input lines on - those terminals. - -9. Finally, it restores the signal process mask to how it - was when \f3gl_handle_signal()\f1 was called. - -Note that the process is suspended or terminated using the original -signal that was caught, rather than using the uncatchable -\f3SIGSTOP\f1 and \f3SIGKILL\f1 signals. This is important, because -when a process is suspended or terminated, the parent of the process -may wish to use the status value returned by the \f3wait()\f1 system -call to figure out which signal was responsible. In particular, most -shells use this information to print a corresponding message to the -terminal. Users would be rightly confused if when their process -received a \f3SIGPIPE\f1 signal, the program responded by sending -itself a \f3SIGKILL\f1 signal, and the shell then printed out the -provocative statement, "Killed!". - -.SH INTERRUPTING THE EVENT LOOP - -If a signal is caught and handled when the application's event loop is -waiting in \f3select()\f1 or \f3poll()\f1, these functions will be -aborted with \f3errno\f1 set to \f3EINTR\f1. When this happens the -event loop should call \f3gl_pending_io()\f1, before calling -\f3select()\f1 or \f3poll()\f1 again. It should then arrange for -\f3select()\f1 or \f3poll()\f1 to wait for the type of I/O that this -reports. This is necessary, because any signal handler which calls -\f3gl_handle_signal()\f1, will frequently change the type of I/O that -\f3gl_get_line()\f1 is waiting for. - -Unfortunately, if a signal arrives between the statements which -configure the arguments of \f3select()\f1 or \f3poll()\f1 and the -calls to these functions, then the signal will not be seen by these -functions, which will then not be aborted. If these functions are -waiting for keyboard input from the user when the signal is received, -and the signal handler arranges to redraw the input line to accomodate -a terminal resize or the resumption of the process, then this -redisplay will be end up being delayed until the user hits the next -key. Apart from puzzling the user, this clearly isn't a serious -problem. However there is a way, albeit complicated, to completely -avoid this race condition. The following steps illustrate this. - -1. Block all of the signals that \f3gl_get_line()\f1 catches, - by passing the signal set returned by \f3gl_list_signals()\f1 to - \f3sigprocmask()\f1. - -2. Call \f3gl_pending_io()\f1 and set up the arguments of - \f3select()\f1 or \f3poll()\f1 accordingly. - -3. Call \f3sigsetjmp()\f1 with a non-zero \f3savesigs\f1 argument. - -4. Initially this \f3sigsetjmp()\f1 statement will return zero, - indicating that control isn't resuming there after a matching - call to \f3siglongjmp()\f1. - -5. Replace all of the handlers of the signals that \f3gl_get_line()\f1 - is configured to catch, with a signal handler that first records - the number of the signal that was caught, in a file-scope variable, - then calls \f3siglongjmp()\f1 with a non-zero value argument, to - return execution to the above \f3sigsetjmp()\f1 - statement. Registering these signal handlers can conveniently be - done using the \f3gl_tty_signals()\f1 function. - -6. Set the file-scope variable that the above signal handler uses to - record any signal that is caught to -1, so that we can check - whether a signal was caught by seeing if it contains a valid signal - number. - -7. Now unblock the signals that were blocked in step 1. Any signal - that was received by the process in between step 1 and now will - now be delivered, and trigger our signal handler, as will any - signal that is received until we block these signals again. - -8. Now call \f3select()\f1 or \f3poll()\f1. - -9. When \f3select()\f1 returns, again block the signals that were - unblocked in step 7. - -If a signal is arrived any time during the above steps, our signal -handler will be triggered and cause control to return to the -\f3sigsetjmp()\f1 statement, where this time, \f3sigsetjmp()\f1 will -return non-zero, indicating that a signal was caught. When this -happens we simply skip the above block of statements, and continue -with the following statements, which are executed regardless of -whether or not a signal is caught. Note that when \f3sigsetjmp()\f1 -returns, regardless of why it returned, the process signal mask is -returned to how it was when \f3sigsetjmp()\f1 was called. Thus the -following statements are always executed with all of our signals -blocked. - -9. Reinstate the signal handlers that were displaced in step 5. - -10. Check wether a signal was caught, by checking the file-scope - variable that the signal handler records signal numbers in. - -11. If a signal was caught, send this signal to the application - again, and unblock just this signal, so that it invokes the - signal handler which we just reinstated in step 10. - -12. Unblock all of the signals that were blocked in step 7. - -Since this is complicated, note that \f3demo3.c\f1 includes a working -example of how to do this. The method used there however, is more -general than the above. What it provides is a wrapper function around -\f3select()\f1 which encompasses steps 3 to 11. In this wrapper, -rather than use \f3gl_list_signals()\f1 to figure out the signals to -block, and and \f3gl_tty_signals()\f1 to assign and revert signal -handlers, one of its arguments is a \f3sigset_t\f1 which specifies -which signals to block and assign signal handlers to. This function -thus doesn't depend on \f3gl_get_line()\f1 and can thus be used in -other situations where race-condition-free signal handling is -required. - -.SH SIGNALS CAUGHT BY GL_GET_LINE - -Since the application is expected to handle signals in non-blocking -server mode, \f3gl_get_line()\f1 doesn't attempt to duplicate this -when it is being called. If one of the signals that it is configured -to catch is sent to the application while \f3gl_get_line()\f1 is being -called, \f3gl_get_line()\f1 reinstates the caller's signal handlers, -then just before returning, re-sends the signal to the process to let -the application's signal handler handle it. If the process isn't -terminated by this signal, \f3gl_get_line()\f1 returns \f3NULL\f1, and -a following call to \f3gl_return_status()\f1 returns the enumerated -value \f3GLR_SIGNAL\f1. - -.SH ABORTING LINE INPUT - -Often, rather than letting it terminate the process, applications -respond to the SIGINT user-interrupt signal by aborting the current -input line. The way to do this in non-blocking server-I/O mode is to -not call \f3gl_handle_signal()\f1 when this signal is caught, but -instead to call the \f3gl_abandon_line()\f1. - -.sp -.nf - void gl_abandon_line(GetLine *gl); -.fi -.sp - -This function arranges that when \f3gl_get_line()\f1 is next called, -it first flushes any pending output to the terminal, then discardes -the current input line, outputs a new prompt on the next line, and -finally starts accepting input of a new input line from the user. - -.SH SIGNAL SAFE FUNCTIONS - -Provided that certain rules are followed, the following functions can -have been written to be safely callable from signal handlers. Other -functions in this library should not be called from signal handlers. - -.sp -.nf - gl_normal_io() - gl_raw_io() - gl_handle_signal() - gl_abandon_line() -.fi -.sp - -In order for this to be true, all signal handlers that call these -functions must be registered in such a way that only one instance of -any one of them can be running at one time. The way to do this is to -use the POSIX \f3sigaction()\f1 function to register all signal -handlers, and when doing this, use the \f3sa_mask\f1 member of the -corresponding sigaction structure, to indicate that all of the signals -who's handlers invoke the above functions, should be blocked when the -current signal is being handled. This prevents two signal handlers -from operating on a \f3GetLine\f1 object at the same time. - -To prevent signal handlers from accessing a \f3GetLine\f1 object while -\f3gl_get_line()\f1 or any of its associated public functions are -operating on it, all public functions associated with -\f3gl_get_line()\f1, including \f3gl_get_line()\f1 itself, temporarily -block the delivery of signals when they are accessing \f3GetLine\f1 -objects. Beware that the only signals that they block are the signals -that \f3gl_get_line()\f1 is currently configured to catch, so be sure -that if you call any of the above functions from signal handlers, that -the signals that these handlers are assigned to are configured to be -caught by \f3gl_get_line()\f1 (see \f3gl_trap_signal()\f1). - -.SH USING TIMEOUTS TO POLL - -If instead of using \f3select()\f1 or \f3poll()\f1 to wait for I/O, -your application just needs to get out of \f3gl_get_line()\f1 -periodically to briefly do something else before returning to accept -input from the user, this can be done in non-blocking server mode by -using the \f3gl_inactivity_timeout()\f1 function (see -\f3gl_get_line(@FUNC_MANEXT@)\f1), to specify that a callback function that -returns \f3GLTO_CONTINUE\f1 should be called whenever -\f3gl_get_line()\f1 has been waiting for I/O for more than a specified -amount of time. - -When this callback is triggered, \f3gl_get_line()\f1 will return -\f3NULL\f1, and a following call to \f3gl_return_status()\f1 will -return \f3GLR_BLOCKED\f1. - -Beware that \f3gl_get_line()\f1 won't return until the user -hasn't typed a key for the specified interval, so if the -interval is long, and the user keeps typing, -\f3gl_get_line()\f1 may not return for a while. In other -words there is no guarantee that it will return in the time -specified. - -.SH THE SERVER DEMO PROGRAM - -The \f3demo3\f1 program that is distributed with the library, provides -a working example of how to use non-blocking server I/O mode in a real -program. As far as the user is concerned, this program operates -identically to the main demo program (called \f3demo\f1), except that -whereas the main demo program uses the normal blocking I/O mode, -\f3demo3\f1 using non-blocking I/O and an external event loop. The -source code can be found in \f3demo3.c\f1, and the comments therein -explain the various steps. - -.SH FILES -.nf -libtecla.a - The tecla library -libtecla.h - The tecla header file. -.fi - -.SH SEE ALSO - -.nf -libtecla(@LIBR_MANEXT@), gl_get_line(@FUNC_MANEXT@), tecla(@MISC_MANEXT@), ef_expand_file(@FUNC_MANEXT@), -cpl_complete_word(@FUNC_MANEXT@), pca_lookup_file(@FUNC_MANEXT@) -.fi - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/man/func/gl_last_signal.in b/libtecla-1.6.1/man/func/gl_last_signal.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_last_signal.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_limit_history.in b/libtecla-1.6.1/man/func/gl_limit_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_limit_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_list_signals.in b/libtecla-1.6.1/man/func/gl_list_signals.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_list_signals.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_load_history.in b/libtecla-1.6.1/man/func/gl_load_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_load_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_lookup_history.in b/libtecla-1.6.1/man/func/gl_lookup_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_lookup_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_normal_io.in b/libtecla-1.6.1/man/func/gl_normal_io.in deleted file mode 100644 index 24798bc..0000000 --- a/libtecla-1.6.1/man/func/gl_normal_io.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_io_mode.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_pending_io.in b/libtecla-1.6.1/man/func/gl_pending_io.in deleted file mode 100644 index 24798bc..0000000 --- a/libtecla-1.6.1/man/func/gl_pending_io.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_io_mode.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_prompt_style.in b/libtecla-1.6.1/man/func/gl_prompt_style.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_prompt_style.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_query_char.in b/libtecla-1.6.1/man/func/gl_query_char.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_query_char.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_range_of_history.in b/libtecla-1.6.1/man/func/gl_range_of_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_range_of_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_raw_io.in b/libtecla-1.6.1/man/func/gl_raw_io.in deleted file mode 100644 index 24798bc..0000000 --- a/libtecla-1.6.1/man/func/gl_raw_io.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_io_mode.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_read_char.in b/libtecla-1.6.1/man/func/gl_read_char.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_read_char.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_register_action.in b/libtecla-1.6.1/man/func/gl_register_action.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_register_action.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_resize_history.in b/libtecla-1.6.1/man/func/gl_resize_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_resize_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_return_status.in b/libtecla-1.6.1/man/func/gl_return_status.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_return_status.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_save_history.in b/libtecla-1.6.1/man/func/gl_save_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_save_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_set_term_size.in b/libtecla-1.6.1/man/func/gl_set_term_size.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_set_term_size.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_show_history.in b/libtecla-1.6.1/man/func/gl_show_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_show_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_size_of_history.in b/libtecla-1.6.1/man/func/gl_size_of_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_size_of_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_state_of_history.in b/libtecla-1.6.1/man/func/gl_state_of_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_state_of_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_terminal_size.in b/libtecla-1.6.1/man/func/gl_terminal_size.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_terminal_size.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_toggle_history.in b/libtecla-1.6.1/man/func/gl_toggle_history.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_toggle_history.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_trap_signal.in b/libtecla-1.6.1/man/func/gl_trap_signal.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_trap_signal.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_tty_signals.in b/libtecla-1.6.1/man/func/gl_tty_signals.in deleted file mode 100644 index 24798bc..0000000 --- a/libtecla-1.6.1/man/func/gl_tty_signals.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_io_mode.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/gl_watch_fd.in b/libtecla-1.6.1/man/func/gl_watch_fd.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/gl_watch_fd.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/libtecla_version.in b/libtecla-1.6.1/man/func/libtecla_version.in deleted file mode 100644 index 31867c4..0000000 --- a/libtecla-1.6.1/man/func/libtecla_version.in +++ /dev/null @@ -1 +0,0 @@ -.so @LIBR_MANDIR@/libtecla.@LIBR_MANEXT@ diff --git a/libtecla-1.6.1/man/func/new_CplFileConf.in b/libtecla-1.6.1/man/func/new_CplFileConf.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/new_CplFileConf.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/new_ExpandFile.in b/libtecla-1.6.1/man/func/new_ExpandFile.in deleted file mode 100644 index 3d0a884..0000000 --- a/libtecla-1.6.1/man/func/new_ExpandFile.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/ef_expand_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/new_GetLine.in b/libtecla-1.6.1/man/func/new_GetLine.in deleted file mode 100644 index 6e46fc6..0000000 --- a/libtecla-1.6.1/man/func/new_GetLine.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/gl_get_line.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/new_PathCache.in b/libtecla-1.6.1/man/func/new_PathCache.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/new_PathCache.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/new_PcaPathConf.in b/libtecla-1.6.1/man/func/new_PcaPathConf.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/new_PcaPathConf.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/new_WordCompletion.in b/libtecla-1.6.1/man/func/new_WordCompletion.in deleted file mode 100644 index 734f281..0000000 --- a/libtecla-1.6.1/man/func/new_WordCompletion.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/cpl_complete_word.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/pca_last_error.in b/libtecla-1.6.1/man/func/pca_last_error.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/pca_last_error.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/pca_lookup_file.in b/libtecla-1.6.1/man/func/pca_lookup_file.in deleted file mode 100644 index 861d205..0000000 --- a/libtecla-1.6.1/man/func/pca_lookup_file.in +++ /dev/null @@ -1,365 +0,0 @@ -.\" Copyright (c) 2001, 2002, 2003, 2004 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 @FUNC_MANEXT@ -.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(@LIBR_MANEXT@) 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(@FUNC_MANEXT@)\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 - -.nf -libtecla(@LIBR_MANEXT@), gl_get_line(@FUNC_MANEXT@), ef_expand_file(@FUNC_MANEXT@), -cpl_complete_word(@FUNC_MANEXT@) -.fi - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/man/func/pca_path_completions.in b/libtecla-1.6.1/man/func/pca_path_completions.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/pca_path_completions.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/pca_scan_path.in b/libtecla-1.6.1/man/func/pca_scan_path.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/pca_scan_path.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/pca_set_check_fn.in b/libtecla-1.6.1/man/func/pca_set_check_fn.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/pca_set_check_fn.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/ppc_file_start.in b/libtecla-1.6.1/man/func/ppc_file_start.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/ppc_file_start.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/func/ppc_literal_escapes.in b/libtecla-1.6.1/man/func/ppc_literal_escapes.in deleted file mode 100644 index dbc4da7..0000000 --- a/libtecla-1.6.1/man/func/ppc_literal_escapes.in +++ /dev/null @@ -1 +0,0 @@ -.so @FUNC_MANDIR@/pca_lookup_file.@FUNC_MANEXT@ diff --git a/libtecla-1.6.1/man/libr/libtecla.in b/libtecla-1.6.1/man/libr/libtecla.in deleted file mode 100644 index 9f9aa75..0000000 --- a/libtecla-1.6.1/man/libr/libtecla.in +++ /dev/null @@ -1,168 +0,0 @@ -.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 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 @LIBR_MANEXT@ -.SH NAME -libtecla - An interactive command-line input library. -.SH SYNOPSIS -.nf -@CC@ ... -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 - tecla(@MISC_MANEXT@) - Use level documentation of the - command-line editing facilities - provided by \f3gl_get_line()\f1. - gl_get_line(@FUNC_MANEXT@) - The interactive line-input module. - gl_io_mode(@FUNC_MANEXT@) - How to use \f3gl_get_line()\f1 in an - incremental, non-blocking fashion. - cpl_complete_word(@FUNC_MANEXT@) - The word completion module. - ef_expand_file(@FUNC_MANEXT@) - The filename expansion module. - pca_lookup_file(@FUNC_MANEXT@) - A directory-list based filename - lookup and completion module. -.fi - -In addition there is one optional application distributed -with the library: - -.nf - enhance(@PROG_MANEXT@) - 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 - -.nf -gl_get_line(@FUNC_MANEXT@), tecla(@MISC_MANEXT@), gl_io_mode(@FUNC_MANEXT@), ef_expand_file(@FUNC_MANEXT@), -cpl_complete_word(@FUNC_MANEXT@), pca_lookup_file(@FUNC_MANEXT@), enhance(@PROG_MANEXT@) -.fi - -.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.6.1/man/misc/tecla.in b/libtecla-1.6.1/man/misc/tecla.in deleted file mode 100644 index 1be2902..0000000 --- a/libtecla-1.6.1/man/misc/tecla.in +++ /dev/null @@ -1,1201 +0,0 @@ -.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 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 tecla @MISC_MANEXT@ -.SH NAME -tecla, teclarc \- The user interface provided by the Tecla library. -.SH DESCRIPTION - -This man page describes the command-line editing features that are -available to users of programs that read keyboard input via the Tecla -library. Users of the tcsh shell will find the default key-bindings -very familiar. Users of the bash shell will also find it quite -familiar, but with a few minor differences, most notably in how -forward and backward searches through the list of historical commands -are performed. There are two major editing modes, one with emacs-like -key-bindings and another with vi-like key-bindings. By default emacs -mode is enabled, but vi mode can alternatively be selected via the -user's configuration file. This file can also be used to change the -bindings of individual keys to suit the user's preferences. By -default, tab completion is provided. If the application hasn't -reconfigured this to complete other types of symbols, then tab -completion completes file-names. - -.SH KEY SEQUENCE NOTATION - -In the rest of this man page, and also in all Tecla configuration -files, key-sequences are expressed as follows. - -.sp -.nf -\f3^A\f1 or \f3C-a\f1 - This is a control-A, entered by pressing the control key at - the same time as the \f3A\f1 key. - -\f3\\E\f1 or \f3M-\f1 - In key-sequences, both of these notations can be entered - either by pressing the escape key, then the following key, or by - pressing the Meta key at the same time as the following 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. - -\f3up\f1 - This refers to the up-arrow key. - -\f3down\f1 - This refers to the down-arrow key. - -\f3left\f1 - This refers to the left-arrow key. - -\f3right\f1 - This refers to the right-arrow key. - -\f3a\f1 - This is just a normal A key. -.fi -.sp - -.SH THE TECLA CONFIGURATION FILE - -By default, Tecla 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 - -If you create a \f3~/.teclarc\f1 configuration file, but it appears to -have no effect on the program, check the documentation of the program -to see if the author chose a different name for this file. - -.SH FILENAME AND TILDE COMPLETION - -With the default key bindings, pressing the TAB key (aka. \f3^I\f1) -results in Tecla attempting to complete the incomplete filename that -precedes the cursor. Tecla 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, -then Tecla 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, Tecla 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, Tecla -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(@LIBR_MANEXT@)\f1 man page for more details. - -.SH FILENAME EXPANSION - -With the default key bindings, pressing \f3^X*\f1 causes Tecla 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(@LIBR_MANEXT@)\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", Tecla -would recall the "ls -l getline.c" line. Pressing \f3M-p\f1 again -would recall the "ls ~/tecla/" line. - -Note that if the string that you are searching for, contains any of -the special characters, *, ?, or '[', then it is interpretted as a -pattern to be matched. Thus, cotinuing with the above example, after -typing in the list of commands shown, if you then typed: - -.nf - *tecla* -.fi - -and hit \f3M-p\f1, then the "emacs ~/tecla/getline.c" line would be -recalled first, since it contains the word tecla somewhere in the -line, Similarly, hitting \f3M-p\f1 again, would recall the "ls -~/tecla/" line, and hitting it once more would recall the "ls -~/tecla/" line. The pattern syntax is the same as that described for -filename expansion, in the \f3ef_expand_file(@LIBR_MANEXT@\f1 man -page. - -.SH HISTORY FILES - -Authors of programs that use the Tecla library have the option of -saving historical command-lines in a file before exiting, and -subsequently reading them back in from this file when the program is -next started. There is no standard name for this file, since it makes -sense for each application to use its own history file, so that -commands from different applications don't get mixed up. - -.SH INTERNATIONAL CHARACTER SETS - -Since libtecla version 1.4.0, Tecla 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 laptop 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 THE AVAILABLE KEY BINDING FUNCTIONS - -The following is a list of the editing functions provided by the Tecla -library. The names in the leftmost column of the list can be used in -configuration files to specify which function a given key or -combination of keys should invoke. They are also used in the next two -sections to list the default key-bindings in emacs and vi modes. - -.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 Tecla 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 -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 \f3^I\f1 is what the TAB key generates, and that \f3^@\f1 -can be generated not only by pressing the control key and the \f3@\f1 -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 earlier section entitled -THE TECLA CONFIGURATION FILE. -.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 \f3^I\f1 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 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 FILES -.nf -libtecla.a - The Tecla library -libtecla.h - The Tecla header file. -~/.teclarc - The personal Tecla customization file. -.fi - -.SH SEE ALSO - -.nf -libtecla(@LIBR_MANEXT@), gl_get_line(@LIBR_MANEXT@), gl_io_mode(@LIBR_MANEXT@), ef_expand_file(@LIBR_MANEXT@), -cpl_complete_word(@LIBR_MANEXT@), pca_lookup_file(@LIBR_MANEXT@) -.fi - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/man/prog/enhance.in b/libtecla-1.6.1/man/prog/enhance.in deleted file mode 100644 index a5c51a6..0000000 --- a/libtecla-1.6.1/man/prog/enhance.in +++ /dev/null @@ -1,89 +0,0 @@ -.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 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 enhance @PROG_MANEXT@ -.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. -.sp -Note that the user-level command-line editing facilities provided by -the Tecla library are documented in the \f3tecla(@MISC_MANEXT@)\f1 man page - -.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 -tecla(@MISC_MANEXT@), libtecla(@LIBR_MANEXT@) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.6.1/pathutil.c b/libtecla-1.6.1/pathutil.c deleted file mode 100644 index 7d3e95c..0000000 --- a/libtecla-1.6.1/pathutil.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/* - * If file-system access is to be excluded, this module has no function, - * so all of its code should be excluded. - */ -#ifndef WITHOUT_FILE_SYSTEM - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> -#include <limits.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) { - errno = ENOMEM; - 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) { - errno = ENOMEM; - 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) { - errno = EINVAL; - 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) { - errno = EINVAL; - 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) { - errno = EINVAL; - 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. - */ -char *_pn_resize_path(PathName *path, size_t length) -{ -/* - * Check the arguments. - */ - if(!path) { - errno = EINVAL; - 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) { - errno = EINVAL; - 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) { - errno = EINVAL; - 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; -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/pathutil.h b/libtecla-1.6.1/pathutil.h deleted file mode 100644 index 5454d91..0000000 --- a/libtecla-1.6.1/pathutil.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef pathutil_h -#define pathutil_h - -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/pcache.c b/libtecla-1.6.1/pcache.c deleted file mode 100644 index 74e4ef5..0000000 --- a/libtecla-1.6.1/pcache.c +++ /dev/null @@ -1,1710 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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. - */ - -/* - * If file-system access is to be excluded, this module has no function, - * so all of its code should be excluded. - */ -#ifndef WITHOUT_FILE_SYSTEM - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> - -#include "libtecla.h" -#include "pathutil.h" -#include "homedir.h" -#include "freelist.h" -#include "direader.h" -#include "stringrp.h" -#include "errmsg.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 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 { - ErrMsg *err; /* The error reporting buffer */ - 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. */ -}; - -/* - * 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) { - errno = ENOMEM; - 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->err = NULL; - 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'; -/* - * Allocate a place to record error messages. - */ - pc->err = _new_ErrMsg(); - if(!pc->err) - return del_PathCache(pc); -/* - * Allocate the freelist of directory list nodes. - */ - pc->node_mem = _new_FreeList(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 error message buffer. - */ - pc->err = _del_ErrMsg(pc->err); -/* - * Delete the memory of the list of path nodes. - */ - pc->node_mem = _del_FreeList(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 ? _err_get_msg(pc->err) : "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->err. - */ -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) { - _err_record_msg(pc->err, "Insufficient memory to record directory name", - END_ERR_MSG); - 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) { - _err_record_msg(pc->err, "Insufficient memory to record directory name", - END_ERR_MSG); - 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->err. - */ -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) { - _err_record_msg(pc->err, "Username too long", END_ERR_MSG); - 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) { - errno = ENOMEM; - 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) { - errno = ENOMEM; - 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) { - _err_record_msg(pc->err, "Insufficient memory to cache new directory.", - END_ERR_MSG); - 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) { - _err_record_msg(pc->err, "Insufficient memory to store directory name.", - END_ERR_MSG); - 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) { - _err_record_msg(pc->err, "Insufficient memory to record filename", - END_ERR_MSG); - return -1; - }; -/* - * Store the filename. - */ - copy = _sg_store_string(mem->sg, pc->path->name, 0); - if(!copy) { - _err_record_msg(pc->err, "Insufficient memory to cache file name.", - END_ERR_MSG); - 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) { - _err_record_msg(pc->err, - "Insufficient memory to extend filename cache.", - END_ERR_MSG); - 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) { - _err_record_msg(pc->err, "Insufficient memory.", END_ERR_MSG); - 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) { - _err_record_msg(pc->err, "Insufficient memory to complete file name", - END_ERR_MSG); - 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) { - _err_record_msg(pc->err, "Insufficient memory to complete file name", - END_ERR_MSG); - 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->err. - */ -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) { - _err_record_msg(pc->err, "Insufficient memory to complete filename", - END_ERR_MSG); - 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->err). - */ -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) { - _err_record_msg(pc->err, _hd_last_home_dir_error(pc->home), END_ERR_MSG); - return 1; - }; -/* - * Append the home directory to the pathname string. - */ - if(_pn_append_to_path(pc->path, homedir, -1, 0) == NULL) { - _err_record_msg(pc->err, - "Insufficient memory for home directory expansion", - END_ERR_MSG); - 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; -} - -#endif /* ifndef WITHOUT_FILE_SYSTEM */ diff --git a/libtecla-1.6.1/stringrp.c b/libtecla-1.6.1/stringrp.c deleted file mode 100644 index 2d84766..0000000 --- a/libtecla-1.6.1/stringrp.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.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) { - errno = EINVAL; - return NULL; - }; -/* - * Allocate the container. - */ - sg = (StringGroup *) malloc(sizeof(StringGroup)); - if(!sg) { - errno = ENOMEM; - 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(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(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. Do this by advancing the node pointer until we find - * a node with length+1 bytes unused, or we get to the end of the list. - */ - 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.6.1/stringrp.h b/libtecla-1.6.1/stringrp.h deleted file mode 100644 index c5fdd3a..0000000 --- a/libtecla-1.6.1/stringrp.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef stringrp_h -#define stringrp_h -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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.6.1/strngmem.c b/libtecla-1.6.1/strngmem.c deleted file mode 100644 index c2637ec..0000000 --- a/libtecla-1.6.1/strngmem.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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 <errno.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: - * 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(unsigned blocking_factor) -{ - StringMem *sm; /* The container to be returned. */ -/* - * Check arguments. - */ - if(blocking_factor < 1) { - errno = EINVAL; - return NULL; - }; -/* - * Allocate the container. - */ - sm = (StringMem *) malloc(sizeof(StringMem)); - if(!sm) { - errno = ENOMEM; - 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(SM_STRLEN, blocking_factor); - if(!sm->fl) - return _del_StringMem(sm, 1); -/* - * Return the free-list container. - */ - return sm; -} - -/*....................................................................... - * Delete a string free-list. - * - * Input: - * 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(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)) { - errno = EBUSY; - return NULL; - }; -/* - * Delete the free-list. - */ - sm->fl = _del_FreeList(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.6.1/strngmem.h b/libtecla-1.6.1/strngmem.h deleted file mode 100644 index 9efef09..0000000 --- a/libtecla-1.6.1/strngmem.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef stringmem_h -#define stringmem_h -/* - * Copyright (c) 2000, 2001, 2002, 2003, 2004 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(unsigned blocking_factor); - -/* - * Delete a string free-list. - */ -StringMem *_del_StringMem(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.6.1/update_html b/libtecla-1.6.1/update_html deleted file mode 100755 index 70f189e..0000000 --- a/libtecla-1.6.1/update_html +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# Convert man pages to html files. - -for dir in man/prog man/libr man/func man/misc man/file; do - for template in $dir/*.in;do - page=`basename "$template" .in` - if [ `wc -l < $template` -gt 1 ]; then - html="html/$page.html" - man2html $template > $html - for ref in libtecla cpl_complete_word ef_expand_file gl_get_line pca_lookup_file enhance gl_io_mode tecla; do - link="$ref.html" - ed -s $html << EOF - %s|$ref[(][^)][^) ]*[)]|<a href="$link"><b>$ref</b></a>|g - w - q -EOF - done - fi - done -done - -# Convert the change log into a web page. - -cd html -echo '<html><head><title>The tecla library change log</title></head>' > changes.html -echo '<body bgcolor="#add8e6"><pre>' >> changes.html -sed 's/&/&/g; s/</\</g; s/>/\>/g' ../CHANGES >> changes.html -echo '</pre></body></html>' >> changes.html - -# Do the same to the release-notes file. - -cd ../html -echo '<html><head><title>The tecla library release notes</title></head>' > release.html -echo '<body bgcolor="#add8e6"><pre>' >> release.html -sed 's/&/&/g; s/</\</g' ../RELEASE.NOTES >> release.html -echo '</pre></body></html>' >> release.html diff --git a/libtecla-1.6.1/update_version b/libtecla-1.6.1/update_version deleted file mode 100755 index c18f714..0000000 --- a/libtecla-1.6.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.6.1/version.c b/libtecla-1.6.1/version.c deleted file mode 100644 index 9e1275e..0000000 --- a/libtecla-1.6.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; -} |