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

📄 option.c

📁 早期freebsd实现
💻 C
字号:
/* * Process command line options. * * Each option is a single letter which controls a program variable. * The options have defaults which may be changed via * the command line option, toggled via the "-" command,  * or queried via the "_" command. */#include "less.h"#include "option.h"static struct option *pendopt;public int plusoption;static char *propt();static char *optstring();static int flip_triple();extern int screen_trashed;extern char *every_first_cmd;/*  * Scan an argument (either from the command line or from the  * LESS environment variable) and process it. */	public voidscan_option(s)	char *s;{	register struct option *o;	register int c;	char *str;	int set_default;	PARG parg;	if (s == NULL)		return;	/*	 * If we have a pending string-valued option, handle it now.	 * This happens if the previous option was, for example, "-P"	 * without a following string.  In that case, the current	 * option is simply the string for the previous option.	 */	if (pendopt != NULL)	{		(*pendopt->ofunc)(INIT, s);		pendopt = NULL;		return;	}	set_default = 0;	while (*s != '\0')	{		/*		 * Check some special cases first.		 */		switch (c = *s++)		{		case ' ':		case '\t':		case END_OPTION_STRING:			continue;		case '-':			/*			 * "-+" means set these options back to their defaults.			 * (They may have been set otherwise by previous 			 * options.)			 */			if (set_default = (*s == '+'))				s++;			continue;		case '+':			/*			 * An option prefixed by a "+" is ungotten, so 			 * that it is interpreted as less commands 			 * processed at the start of the first input file.			 * "++" means process the commands at the start of			 * EVERY input file.			 */			plusoption = 1;			if (*s == '+')				every_first_cmd = save(++s);			else				ungetsc(s);			s = optstring(s, c);			continue;		case '0':  case '1':  case '2':  case '3':  case '4':		case '5':  case '6':  case '7':  case '8':  case '9':			/*			 * Special "more" compatibility form "-<number>"			 * instead of -z<number> to set the scrolling 			 * window size.			 */			s--;			c = 'z';			break;		}		/*		 * Not a special case.		 * Look up the option letter in the option table.		 */		o = findopt(c);		if (o == NULL)		{			parg.p_string = propt(c);			error("There is no %s flag (\"less -\\?\" for help)",				&parg);			quit(1);		}		switch (o->otype & OTYPE)		{		case BOOL:			if (set_default)				*(o->ovar) = o->odefault;			else				*(o->ovar) = ! o->odefault;			break;		case TRIPLE:			if (set_default)				*(o->ovar) = o->odefault;			else				*(o->ovar) = flip_triple(o->odefault,						(o->oletter == c));			break;		case STRING:			if (*s == '\0')			{				/*				 * Set pendopt and return.				 * We will get the string next time				 * scan_option is called.				 */				pendopt = o;				return;			}			/*			 * Don't do anything here.			 * All processing of STRING options is done by 			 * the handling function.			 */			str = s;			s = optstring(s, c);			break;		case NUMBER:			*(o->ovar) = getnum(&s, c, (int*)NULL);			break;		}		/*		 * If the option has a handling function, call it.		 */		if (o->ofunc != NULL)			(*o->ofunc)(INIT, str);	}}/* * Toggle command line flags from within the program. * Used by the "-" and "_" commands. * how_toggle may be: *	OPT_NO_TOGGLE	just report the current setting, without changing it. *	OPT_TOGGLE	invert the current setting *	OPT_UNSET	set to the default value *	OPT_SET		set to the inverse of the default value */	public voidtoggle_option(c, s, how_toggle)	int c;	char *s;	int how_toggle;{	register struct option *o;	register int num;	int err;	PARG parg;	/*	 * Look up the option letter in the option table.	 */	o = findopt(c);	if (o == NULL)	{		parg.p_string = propt(c);		error("There is no %s flag", &parg);		return;	}	if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))	{		parg.p_string = propt(c);		error("Cannot change the %s flag", &parg);		return;	} 	/*	 * Check for something which appears to be a do_toggle	 * (because the "-" command was used), but really is not.	 * This could be a string option with no string, or	 * a number option with no number.	 */	switch (o->otype & OTYPE)	{	case STRING:	case NUMBER:		if (how_toggle == OPT_TOGGLE && *s == '\0')			how_toggle = OPT_NO_TOGGLE;		break;	}	/*	 * Now actually toggle (change) the variable.	 */	if (how_toggle != OPT_NO_TOGGLE)	{		switch (o->otype & OTYPE)		{		case BOOL:			/*			 * Boolean.			 */			switch (how_toggle)			{			case OPT_TOGGLE:				*(o->ovar) = ! *(o->ovar);				break;			case OPT_UNSET:				*(o->ovar) = o->odefault;				break;			case OPT_SET:				*(o->ovar) = ! o->odefault;				break;			}			break;		case TRIPLE:			/*			 * Triple:			 *	If user gave the lower case letter, then switch 			 *	to 1 unless already 1, in which case make it 0.			 *	If user gave the upper case letter, then switch			 *	to 2 unless already 2, in which case make it 0.			 */			switch (how_toggle)			{			case OPT_TOGGLE:				*(o->ovar) = flip_triple(*(o->ovar), 						o->oletter == c);				break;			case OPT_UNSET:				*(o->ovar) = o->odefault;				break;			case OPT_SET:				*(o->ovar) = flip_triple(o->odefault,						o->oletter == c);				break;			}			break;		case STRING:			/*			 * String: don't do anything here.			 *	The handling function will do everything.			 */			switch (how_toggle)			{			case OPT_SET:			case OPT_UNSET:				error("Can't use \"-+\" or \"--\" for a string flag",					NULL_PARG);				return;			}			break;		case NUMBER:			/*			 * Number: set the variable to the given number.			 */			switch (how_toggle)			{			case OPT_TOGGLE:				num = getnum(&s, '\0', &err);				if (!err)					*(o->ovar) = num;				break;			case OPT_UNSET:				*(o->ovar) = o->odefault;				break;			case OPT_SET:				error("Can't use \"--\" for a numeric flag",					NULL_PARG);				return;			}			break;		}	}	/*	 * Call the handling function for any special action 	 * specific to this option.	 */	if (o->ofunc != NULL)		(*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);	/*	 * Print a message describing the new setting.	 */	switch (o->otype & OTYPE)	{	case BOOL:	case TRIPLE:		/*		 * Print the odesc message.		 */		error(o->odesc[*(o->ovar)], NULL_PARG);		break;	case NUMBER:		/*		 * The message is in odesc[1] and has a %d for 		 * the value of the variable.		 */		parg.p_int = *(o->ovar);		error(o->odesc[1], &parg);		break;	case STRING:		/*		 * Message was already printed by the handling function.		 */		break;	}	if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))		screen_trashed = 1;}/* * "Toggle" a triple-valued option. */	static intflip_triple(val, lc)	int val;	int lc;{	if (lc)		return ((val == 1) ? 0 : 1);	else		return ((val == 2) ? 0 : 2);}/* * Return a string suitable for printing as the "name" of an option. * For example, if the option letter is 'x', just return "-x". */	static char *propt(c)	int c;{	static char buf[8];	sprintf(buf, "-%s", prchar(c));	return (buf);}/* * Determine if an option is a single character option (BOOL or TRIPLE), * or if it a multi-character option (NUMBER). */	public intsingle_char_option(c)	int c;{	register struct option *o;	o = findopt(c);	if (o == NULL)		return (1);	return (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE));}/* * Return the prompt to be used for a given option letter. * Only string and number valued options have prompts. */	public char *opt_prompt(c)	int c;{	register struct option *o;	o = findopt(c);	if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)		return (NULL);	return (o->odesc[0]);}/* * Return whether or not there is a string option pending; * that is, if the previous option was a string-valued option letter  * (like -P) without a following string. * In that case, the current option is taken to be the string for * the previous option. */	public intisoptpending(){	return (pendopt != NULL);}/* * Print error message about missing string. */	static voidnostring(c)	int c;{	PARG parg;	parg.p_string = propt(c);	error("String is required after %s", &parg);}/* * Print error message if a STRING type option is not followed by a string. */	public voidnopendopt(){	nostring(pendopt->oletter);}/* * Scan to end of string or to an END_OPTION_STRING character. * In the latter case, replace the char with a null char. * Return a pointer to the remainder of the string, if any. */	static char *optstring(s, c)	char *s;	int c;{	register char *p;	if (*s == '\0')	{		nostring(c);		quit(1);	}	for (p = s;  *p != '\0';  p++)		if (*p == END_OPTION_STRING)		{			*p = '\0';			return (p+1);		}	return (p);}/* * Translate a string into a number. * Like atoi(), but takes a pointer to a char *, and updates * the char * to point after the translated number. */	public intgetnum(sp, c, errp)	char **sp;	int c;	int *errp;{	register char *s;	register int n;	register int neg;	PARG parg;	s = skipsp(*sp);	neg = 0;	if (*s == '-')	{		neg = 1;		s++;	}	if (*s < '0' || *s > '9')	{		if (errp != NULL)		{			*errp = 1;			return (-1);		}		parg.p_string = propt(c);		error("Number is required after %s", &parg);		quit(1);	}	n = 0;	while (*s >= '0' && *s <= '9')		n = 10 * n + *s++ - '0';	*sp = s;	if (errp != NULL)		*errp = 0;	if (neg)		n = -n;	return (n);}

⌨️ 快捷键说明

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