⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readline.c

📁 asterisk 是一个很有知名度开源软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	$NetBSD: readline.c,v 1.21 2002/03/18 16:20:36 christos Exp $	*//*- * Copyright (c) 1997 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jaromir Dolecek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the NetBSD *	Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#if !defined(lint) && !defined(SCCSID)__RCSID("$NetBSD: readline.c,v 1.21 2002/03/18 16:20:36 christos Exp $");#endif /* not lint && not SCCSID */#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <dirent.h>#include <string.h>#include <pwd.h>#include <ctype.h>#include <stdlib.h>#include <unistd.h>#include <limits.h>#ifdef SOLARIS#include <alloca.h>#endif#include "histedit.h"#include "readline/readline.h"#include "el.h"#include "fcns.h"		/* for EL_NUM_FCNS *//* for rl_complete() */#define	TAB		'\r'/* see comment at the #ifdef for sense of this */#define	GDB_411_HACK/* readline compatibility stuff - look at readline sources/documentation *//* to see what these variables mean */const char *rl_library_version = "EditLine wrapper";static char empty[] = { '\0' };static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',    '>', '<', '=', ';', '|', '&', '{', '(', '\0' };char *rl_readline_name = empty;FILE *rl_instream = NULL;FILE *rl_outstream = NULL;int rl_point = 0;int rl_end = 0;char *rl_line_buffer = NULL;int history_base = 1;		/* probably never subject to change */int history_length = 0;int max_input_history = 0;char history_expansion_char = '!';char history_subst_char = '^';char *history_no_expand_chars = expand_chars;Function *history_inhibit_expansion_function = NULL;int rl_inhibit_completion = 0;int rl_attempted_completion_over = 0;char *rl_basic_word_break_characters = break_chars;char *rl_completer_word_break_characters = NULL;char *rl_completer_quote_characters = NULL;CPFunction *rl_completion_entry_function = NULL;CPPFunction *rl_attempted_completion_function = NULL;/* * This is set to character indicating type of completion being done by * rl_complete_internal(); this is available for application completion * functions. */int rl_completion_type = 0;/* * If more than this number of items results from query for possible * completions, we ask user if they are sure to really display the list. */int rl_completion_query_items = 100;/* * List of characters which are word break characters, but should be left * in the parsed text when it is passed to the completion function. * Shell uses this to help determine what kind of completing to do. */char *rl_special_prefixes = (char *)NULL;/* * This is the character appended to the completed words if at the end of * the line. Default is ' ' (a space). */int rl_completion_append_character = ' ';/* stuff below is used internally by libedit for readline emulation *//* if not zero, non-unique completions always show list of possible matches */static int _rl_complete_show_all = 0;static History *h = NULL;static EditLine *e = NULL;static int el_rl_complete_cmdnum = 0;/* internal functions */static unsigned char	 _el_rl_complete(EditLine *, int);static char		*_get_prompt(EditLine *);static HIST_ENTRY	*_move_history(int);static int		 _history_search_gen(const char *, int, int);static int		 _history_expand_command(const char *, size_t, char **);static char		*_rl_compat_sub(const char *, const char *,			    const char *, int);static int		 rl_complete_internal(int);static int		 _rl_qsort_string_compare(const void *, const void *);/* * needed for prompt switching in readline() */static char *el_rl_prompt = NULL;/* ARGSUSED */static char *_get_prompt(EditLine *el){	return (el_rl_prompt);}/* * generic function for moving around history */static HIST_ENTRY *_move_history(int op){	HistEvent ev;	static HIST_ENTRY rl_he;	if (history(h, &ev, op) != 0)		return (HIST_ENTRY *) NULL;	rl_he.line = ev.str;	rl_he.data = "";	return (&rl_he);}/* * READLINE compatibility stuff *//* * initialize rl compat stuff */intrl_initialize(void){	HistEvent ev;	const LineInfo *li;	int i;	int editmode = 1;	struct termios t;	if (e != NULL)		el_end(e);	if (h != NULL)		history_end(h);	if (!rl_instream)		rl_instream = stdin;	if (!rl_outstream)		rl_outstream = stdout;	/*	 * See if we don't really want to run the editor	 */	if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)		editmode = 0;	e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);	if (!editmode)		el_set(e, EL_EDITMODE, 0);	h = history_init();	if (!e || !h)		return (-1);	history(h, &ev, H_SETSIZE, INT_MAX);	/* unlimited */	history_length = 0;	max_input_history = INT_MAX;	el_set(e, EL_HIST, history, h);	/* for proper prompt printing in readline() */	el_rl_prompt = strdup("");	el_set(e, EL_PROMPT, _get_prompt);	el_set(e, EL_SIGNAL, 1);	/* set default mode to "emacs"-style and read setting afterwards */	/* so this can be overriden */	el_set(e, EL_EDITOR, "emacs");	/*	 * Word completition - this has to go AFTER rebinding keys	 * to emacs-style.	 */	el_set(e, EL_ADDFN, "rl_complete",	    "ReadLine compatible completition function",	    _el_rl_complete);	el_set(e, EL_BIND, "^I", "rl_complete", NULL);	/*	 * Find out where the rl_complete function was added; this is	 * used later to detect that lastcmd was also rl_complete.	 */	for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {		if (e->el_map.func[i] == _el_rl_complete) {			el_rl_complete_cmdnum = i;			break;		}	}			/* read settings from configuration file */	el_source(e, NULL);	/*	 * Unfortunately, some applications really do use rl_point	 * and rl_line_buffer directly.	 */	li = el_line(e);	/* a cheesy way to get rid of const cast. */	rl_line_buffer = memchr(li->buffer, *li->buffer, 1);	rl_point = rl_end = 0;	return (0);}/* * read one line from input stream and return it, chomping * trailing newline (if there is any) */char *readline(const char *prompt){	HistEvent ev;	int count;	const char *ret;	char *buf;	if (e == NULL || h == NULL)		rl_initialize();	/* update prompt accordingly to what has been passed */	if (!prompt)		prompt = "";	if (strcmp(el_rl_prompt, prompt) != 0) {		free(el_rl_prompt);		el_rl_prompt = strdup(prompt);	}	/* get one line from input stream */	ret = el_gets(e, &count);	if (ret && count > 0) {		int lastidx;		buf = strdup(ret);		lastidx = count - 1;		if (buf[lastidx] == '\n')			buf[lastidx] = '\0';	} else		buf = NULL;	history(h, &ev, H_GETSIZE);	history_length = ev.num;	return buf;}/* * history functions *//* * is normally called before application starts to use * history expansion functions */voidusing_history(void){	if (h == NULL || e == NULL)		rl_initialize();}/* * substitute ``what'' with ``with'', returning resulting string; if * globally == 1, substitutes all occurences of what, otherwise only the * first one */static char *_rl_compat_sub(const char *str, const char *what, const char *with,    int globally){	char *result;	const char *temp, *new;	int len, with_len, what_len, add;	size_t size, i;	result = malloc((size = 16));	temp = str;	with_len = strlen(with);	what_len = strlen(what);	len = 0;	do {		new = strstr(temp, what);		if (new) {			i = new - temp;			add = i + with_len;			if (i + add + 1 >= size) {				size += add + 1;				result = realloc(result, size);			}			(void) strncpy(&result[len], temp, i);			len += i;			(void) strcpy(&result[len], with);	/* safe */			len += with_len;			temp = new + what_len;		} else {			add = strlen(temp);			if (len + add + 1 >= size) {				size += add + 1;				result = realloc(result, size);			}			(void) strcpy(&result[len], temp);	/* safe */			len += add;			temp = NULL;		}	} while (temp && globally);	result[len] = '\0';	return (result);}/* * the real function doing history expansion - takes as argument command * to do and data upon which the command should be executed * does expansion the way I've understood readline documentation * word designator ``%'' isn't supported (yet ?) * * returns 0 if data was not modified, 1 if it was and 2 if the string * should be only printed and not executed; in case of error, * returns -1 and *result points to NULL * it's callers responsibility to free() string returned in *result */static int_history_expand_command(const char *command, size_t cmdlen, char **result){	char **arr, *tempcmd, *line, *search = NULL, *cmd;	const char *event_data = NULL;	static char *from = NULL, *to = NULL;	int start = -1, end = -1, max, i, idx;	int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0;	int event_num = 0, retval;	size_t cmdsize;	*result = NULL;	cmd = alloca(cmdlen + 1);	(void) strncpy(cmd, command, cmdlen);	cmd[cmdlen] = 0;	idx = 1;	/* find out which event to take */	if (cmd[idx] == history_expansion_char) {		event_num = history_length;		idx++;	} else {		int off, num;		size_t len;		off = idx;		while (cmd[off] && !strchr(":^$*-%", cmd[off]))			off++;		num = atoi(&cmd[idx]);		if (num != 0) {			event_num = num;			if (num < 0)				event_num += history_length + 1;		} else {			int prefix = 1, curr_num;			HistEvent ev;			len = off - idx;			if (cmd[idx] == '?') {				idx++, len--;				if (cmd[off - 1] == '?')					len--;				else if (cmd[off] != '\n' && cmd[off] != '\0')					return (-1);				prefix = 0;			}			search = alloca(len + 1);			(void) strncpy(search, &cmd[idx], len);			search[len] = '\0';			if (history(h, &ev, H_CURR) != 0)				return (-1);			curr_num = ev.num;			if (prefix)				retval = history_search_prefix(search, -1);			else				retval = history_search(search, -1);			if (retval == -1) {				fprintf(rl_outstream, "%s: Event not found\n",				    search);				return (-1);			}			if (history(h, &ev, H_CURR) != 0)				return (-1);			event_data = ev.str;			/* roll back to original position */			history(h, &ev, H_NEXT_EVENT, curr_num);		}		idx = off;	}	if (!event_data && event_num >= 0) {		HIST_ENTRY *rl_he;		rl_he = history_get(event_num);		if (!rl_he)			return (0);		event_data = rl_he->line;	} else		return (-1);	if (cmd[idx] != ':')		return (-1);	cmd += idx + 1;	/* recognize cmd */	if (*cmd == '^')		start = end = 1, cmd++;	else if (*cmd == '$')		start = end = -1, cmd++;	else if (*cmd == '*')		start = 1, end = -1, cmd++;	else if (isdigit((unsigned char) *cmd)) {		const char *temp;		int shifted = 0;		start = atoi(cmd);		temp = cmd;		for (; isdigit((unsigned char) *cmd); cmd++);		if (temp != cmd)			shifted = 1;		if (shifted && *cmd == '-') {			if (!isdigit((unsigned char) *(cmd + 1)))				end = -2;			else {				end = atoi(cmd + 1);				for (; isdigit((unsigned char) *cmd); cmd++);			}		} else if (shifted && *cmd == '*')			end = -1, cmd++;		else if (shifted)			end = start;	}	if (*cmd == ':')		cmd++;	line = strdup(event_data);	for (; *cmd; cmd++) {		if (*cmd == ':')			continue;		else if (*cmd == 'h')			h_on = 1 | g_on, g_on = 0;		else if (*cmd == 't')			t_on = 1 | g_on, g_on = 0;		else if (*cmd == 'r')			r_on = 1 | g_on, g_on = 0;		else if (*cmd == 'e')			e_on = 1 | g_on, g_on = 0;		else if (*cmd == 'p')			p_on = 1 | g_on, g_on = 0;		else if (*cmd == 'g')			g_on = 2;		else if (*cmd == 's' || *cmd == '&') {			char *what, *with, delim;			int len, from_len;			size_t size;			if (*cmd == '&' && (from == NULL || to == NULL))				continue;			else if (*cmd == 's') {				delim = *(++cmd), cmd++;				size = 16;				what = realloc(from, size);				len = 0;				for (; *cmd && *cmd != delim; cmd++) {					if (*cmd == '\\'					    && *(cmd + 1) == delim)						cmd++;					if (len >= size)						what = realloc(what,						    (size <<= 1));					what[len++] = *cmd;				}				what[len] = '\0';				from = what;				if (*what == '\0') {					free(what);					if (search)						from = strdup(search);					else {						from = NULL;						return (-1);					}				}				cmd++;	/* shift after delim */				if (!*cmd)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -