mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 18:10:56 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			935 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			935 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * options.c - shell options
 | |
|  *
 | |
|  * This file is part of zsh, the Z shell.
 | |
|  *
 | |
|  * Copyright (c) 1992-1997 Paul Falstad
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * Permission is hereby granted, without written agreement and without
 | |
|  * license or royalty fees, to use, copy, modify, and distribute this
 | |
|  * software and to distribute modified versions of this software for any
 | |
|  * purpose, provided that the above copyright notice and the following
 | |
|  * two paragraphs appear in all copies of this software.
 | |
|  *
 | |
|  * In no event shall Paul Falstad or the Zsh Development Group be liable
 | |
|  * to any party for direct, indirect, special, incidental, or consequential
 | |
|  * damages arising out of the use of this software and its documentation,
 | |
|  * even if Paul Falstad and the Zsh Development Group have been advised of
 | |
|  * the possibility of such damage.
 | |
|  *
 | |
|  * Paul Falstad and the Zsh Development Group specifically disclaim any
 | |
|  * warranties, including, but not limited to, the implied warranties of
 | |
|  * merchantability and fitness for a particular purpose.  The software
 | |
|  * provided hereunder is on an "as is" basis, and Paul Falstad and the
 | |
|  * Zsh Development Group have no obligation to provide maintenance,
 | |
|  * support, updates, enhancements, or modifications.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "zsh.mdh"
 | |
| #include "options.pro"
 | |
| 
 | |
| /* current emulation (used to decide which set of option letters is used) */
 | |
| 
 | |
| /**/
 | |
| mod_export int emulation;
 | |
|  
 | |
| /* current sticky emulation:  sticky = NULL means none */
 | |
| 
 | |
| /**/
 | |
| mod_export Emulation_options sticky;
 | |
| 
 | |
| /* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */
 | |
| 
 | |
| /**/
 | |
| mod_export char opts[OPT_SIZE];
 | |
| 
 | |
| /* Option name hash table */
 | |
| 
 | |
| /**/
 | |
| mod_export HashTable optiontab;
 | |
| 
 | |
| /* The canonical option name table */
 | |
| 
 | |
| #define OPT_CSH		EMULATE_CSH
 | |
| #define OPT_KSH		EMULATE_KSH
 | |
| #define OPT_SH		EMULATE_SH
 | |
| #define OPT_ZSH		EMULATE_ZSH
 | |
| 
 | |
| #define OPT_ALL		(OPT_CSH|OPT_KSH|OPT_SH|OPT_ZSH)
 | |
| #define OPT_BOURNE	(OPT_KSH|OPT_SH)
 | |
| #define OPT_BSHELL	(OPT_KSH|OPT_SH|OPT_ZSH)
 | |
| #define OPT_NONBOURNE	(OPT_ALL & ~OPT_BOURNE)
 | |
| #define OPT_NONZSH	(OPT_ALL & ~OPT_ZSH)
 | |
| 
 | |
| /* option is relevant to emulation */
 | |
| #define OPT_EMULATE	(EMULATE_UNUSED)
 | |
| /* option should never be set by emulate() */
 | |
| #define OPT_SPECIAL	(EMULATE_UNUSED<<1)
 | |
| /* option is an alias to an other option */
 | |
| #define OPT_ALIAS	(EMULATE_UNUSED<<2)
 | |
| 
 | |
| #define defset(X, my_emulation) (!!((X)->node.flags & my_emulation))
 | |
| 
 | |
| /*
 | |
|  * Note that option names should usually be fewer than 20 characters long
 | |
|  * to avoid formatting problems.
 | |
|  */
 | |
| static struct optname optns[] = {
 | |
| {{NULL, "aliases",	      OPT_EMULATE|OPT_ALL},	 ALIASESOPT},
 | |
| {{NULL, "allexport",	      OPT_EMULATE},		 ALLEXPORT},
 | |
| {{NULL, "alwayslastprompt",   OPT_ALL},			 ALWAYSLASTPROMPT},
 | |
| {{NULL, "alwaystoend",	      0},			 ALWAYSTOEND},
 | |
| {{NULL, "appendcreate",	      OPT_EMULATE|OPT_BOURNE},	 APPENDCREATE},
 | |
| {{NULL, "appendhistory",      OPT_ALL},			 APPENDHISTORY},
 | |
| {{NULL, "autocd",	      OPT_EMULATE},		 AUTOCD},
 | |
| {{NULL, "autocontinue",	      0},			 AUTOCONTINUE},
 | |
| {{NULL, "autolist",	      OPT_ALL},			 AUTOLIST},
 | |
| {{NULL, "automenu",	      OPT_ALL},			 AUTOMENU},
 | |
| {{NULL, "autonamedirs",	      0},			 AUTONAMEDIRS},
 | |
| {{NULL, "autoparamkeys",      OPT_ALL},			 AUTOPARAMKEYS},
 | |
| {{NULL, "autoparamslash",     OPT_ALL},			 AUTOPARAMSLASH},
 | |
| {{NULL, "autopushd",	      0},			 AUTOPUSHD},
 | |
| {{NULL, "autoremoveslash",    OPT_ALL},			 AUTOREMOVESLASH},
 | |
| {{NULL, "autoresume",	      0},			 AUTORESUME},
 | |
| {{NULL, "badpattern",	      OPT_EMULATE|OPT_NONBOURNE},BADPATTERN},
 | |
| {{NULL, "banghist",	      OPT_NONBOURNE},		 BANGHIST},
 | |
| {{NULL, "bareglobqual",       OPT_EMULATE|OPT_ZSH},      BAREGLOBQUAL},
 | |
| {{NULL, "bashautolist",	      0},                        BASHAUTOLIST},
 | |
| {{NULL, "bashrematch",	      0},			 BASHREMATCH},
 | |
| {{NULL, "beep",		      OPT_ALL},			 BEEP},
 | |
| {{NULL, "bgnice",	      OPT_EMULATE|OPT_NONBOURNE},BGNICE},
 | |
| {{NULL, "braceccl",	      OPT_EMULATE},		 BRACECCL},
 | |
| {{NULL, "bsdecho",	      OPT_EMULATE|OPT_SH},	 BSDECHO},
 | |
| {{NULL, "caseglob",	      OPT_ALL},			 CASEGLOB},
 | |
| {{NULL, "casematch",	      OPT_ALL},			 CASEMATCH},
 | |
| {{NULL, "cbases",	      0},			 CBASES},
 | |
| {{NULL, "cprecedences",	      OPT_EMULATE|OPT_NONZSH},	 CPRECEDENCES},
 | |
| {{NULL, "cdablevars",	      OPT_EMULATE},		 CDABLEVARS},
 | |
| {{NULL, "chasedots",	      OPT_EMULATE},		 CHASEDOTS},
 | |
| {{NULL, "chaselinks",	      OPT_EMULATE},		 CHASELINKS},
 | |
| {{NULL, "checkjobs",	      OPT_EMULATE|OPT_ZSH},	 CHECKJOBS},
 | |
| {{NULL, "clobber",	      OPT_EMULATE|OPT_ALL},	 CLOBBER},
 | |
| {{NULL, "combiningchars",     0},			 COMBININGCHARS},
 | |
| {{NULL, "completealiases",    0},			 COMPLETEALIASES},
 | |
| {{NULL, "completeinword",     0},			 COMPLETEINWORD},
 | |
| {{NULL, "continueonerror",    0},                        CONTINUEONERROR},
 | |
| {{NULL, "correct",	      0},			 CORRECT},
 | |
| {{NULL, "correctall",	      0},			 CORRECTALL},
 | |
| {{NULL, "cshjunkiehistory",   OPT_EMULATE|OPT_CSH},	 CSHJUNKIEHISTORY},
 | |
| {{NULL, "cshjunkieloops",     OPT_EMULATE|OPT_CSH},	 CSHJUNKIELOOPS},
 | |
| {{NULL, "cshjunkiequotes",    OPT_EMULATE|OPT_CSH},	 CSHJUNKIEQUOTES},
 | |
| {{NULL, "cshnullcmd",	      OPT_EMULATE|OPT_CSH},	 CSHNULLCMD},
 | |
| {{NULL, "cshnullglob",	      OPT_EMULATE|OPT_CSH},	 CSHNULLGLOB},
 | |
| {{NULL, "debugbeforecmd",     OPT_ALL},			 DEBUGBEFORECMD},
 | |
| {{NULL, "emacs",	      0},			 EMACSMODE},
 | |
| {{NULL, "equals",	      OPT_EMULATE|OPT_ZSH},	 EQUALS},
 | |
| {{NULL, "errexit",	      OPT_EMULATE},		 ERREXIT},
 | |
| {{NULL, "errreturn",	      OPT_EMULATE},		 ERRRETURN},
 | |
| {{NULL, "exec",		      OPT_ALL},			 EXECOPT},
 | |
| {{NULL, "extendedglob",	      OPT_EMULATE},		 EXTENDEDGLOB},
 | |
| {{NULL, "extendedhistory",    OPT_CSH},			 EXTENDEDHISTORY},
 | |
| {{NULL, "evallineno",	      OPT_EMULATE|OPT_ZSH},	 EVALLINENO},
 | |
| {{NULL, "flowcontrol",	      OPT_ALL},			 FLOWCONTROL},
 | |
| {{NULL, "forcefloat",         0},                        FORCEFLOAT},
 | |
| {{NULL, "functionargzero",    OPT_EMULATE|OPT_NONBOURNE},FUNCTIONARGZERO},
 | |
| {{NULL, "glob",		      OPT_EMULATE|OPT_ALL},	 GLOBOPT},
 | |
| {{NULL, "globalexport",       OPT_EMULATE|OPT_ZSH},	 GLOBALEXPORT},
 | |
| {{NULL, "globalrcs",          OPT_ALL},			 GLOBALRCS},
 | |
| {{NULL, "globassign",	      OPT_EMULATE|OPT_CSH},	 GLOBASSIGN},
 | |
| {{NULL, "globcomplete",	      0},			 GLOBCOMPLETE},
 | |
| {{NULL, "globdots",	      OPT_EMULATE},		 GLOBDOTS},
 | |
| {{NULL, "globstarshort",      OPT_EMULATE},		 GLOBSTARSHORT},
 | |
| {{NULL, "globsubst",	      OPT_EMULATE|OPT_NONZSH},	 GLOBSUBST},
 | |
| {{NULL, "hashcmds",	      OPT_ALL},			 HASHCMDS},
 | |
| {{NULL, "hashdirs",	      OPT_ALL},			 HASHDIRS},
 | |
| {{NULL, "hashexecutablesonly", 0},                       HASHEXECUTABLESONLY},
 | |
| {{NULL, "hashlistall",	      OPT_ALL},			 HASHLISTALL},
 | |
| {{NULL, "histallowclobber",   0},			 HISTALLOWCLOBBER},
 | |
| {{NULL, "histbeep",	      OPT_ALL},			 HISTBEEP},
 | |
| {{NULL, "histexpiredupsfirst",0},			 HISTEXPIREDUPSFIRST},
 | |
| {{NULL, "histfcntllock",      0},			 HISTFCNTLLOCK},
 | |
| {{NULL, "histfindnodups",     0},			 HISTFINDNODUPS},
 | |
| {{NULL, "histignorealldups",  0},			 HISTIGNOREALLDUPS},
 | |
| {{NULL, "histignoredups",     0},			 HISTIGNOREDUPS},
 | |
| {{NULL, "histignorespace",    0},			 HISTIGNORESPACE},
 | |
| {{NULL, "histlexwords",	      0},			 HISTLEXWORDS},
 | |
| {{NULL, "histnofunctions",    0},			 HISTNOFUNCTIONS},
 | |
| {{NULL, "histnostore",	      0},			 HISTNOSTORE},
 | |
| {{NULL, "histsubstpattern",   OPT_EMULATE},              HISTSUBSTPATTERN},
 | |
| {{NULL, "histreduceblanks",   0},			 HISTREDUCEBLANKS},
 | |
| {{NULL, "histsavebycopy",     OPT_ALL},			 HISTSAVEBYCOPY},
 | |
| {{NULL, "histsavenodups",     0},			 HISTSAVENODUPS},
 | |
| {{NULL, "histverify",	      0},			 HISTVERIFY},
 | |
| {{NULL, "hup",		      OPT_EMULATE|OPT_ZSH},	 HUP},
 | |
| {{NULL, "ignorebraces",	      OPT_EMULATE|OPT_SH},	 IGNOREBRACES},
 | |
| {{NULL, "ignoreclosebraces",  OPT_EMULATE},		 IGNORECLOSEBRACES},
 | |
| {{NULL, "ignoreeof",	      0},			 IGNOREEOF},
 | |
| {{NULL, "incappendhistory",   0},			 INCAPPENDHISTORY},
 | |
| {{NULL, "incappendhistorytime",   0},			 INCAPPENDHISTORYTIME},
 | |
| {{NULL, "interactive",	      OPT_SPECIAL},		 INTERACTIVE},
 | |
| {{NULL, "interactivecomments",OPT_BOURNE},		 INTERACTIVECOMMENTS},
 | |
| {{NULL, "ksharrays",	      OPT_EMULATE|OPT_BOURNE},	 KSHARRAYS},
 | |
| {{NULL, "kshautoload",	      OPT_EMULATE|OPT_BOURNE},	 KSHAUTOLOAD},
 | |
| {{NULL, "kshglob",	      OPT_EMULATE|OPT_KSH},	 KSHGLOB},
 | |
| {{NULL, "kshoptionprint",     OPT_EMULATE|OPT_KSH},	 KSHOPTIONPRINT},
 | |
| {{NULL, "kshtypeset",	      0},			 KSHTYPESET},
 | |
| {{NULL, "kshzerosubscript",   0},			 KSHZEROSUBSCRIPT},
 | |
| {{NULL, "listambiguous",      OPT_ALL},			 LISTAMBIGUOUS},
 | |
| {{NULL, "listbeep",	      OPT_ALL},			 LISTBEEP},
 | |
| {{NULL, "listpacked",	      0},			 LISTPACKED},
 | |
| {{NULL, "listrowsfirst",      0},			 LISTROWSFIRST},
 | |
| {{NULL, "listtypes",	      OPT_ALL},			 LISTTYPES},
 | |
| {{NULL, "localoptions",	      OPT_EMULATE|OPT_KSH},	 LOCALOPTIONS},
 | |
| {{NULL, "localloops",	      OPT_EMULATE},		 LOCALLOOPS},
 | |
| {{NULL, "localpatterns",      OPT_EMULATE},		 LOCALPATTERNS},
 | |
| {{NULL, "localtraps",	      OPT_EMULATE|OPT_KSH},	 LOCALTRAPS},
 | |
| {{NULL, "login",	      OPT_SPECIAL},		 LOGINSHELL},
 | |
| {{NULL, "longlistjobs",	      0},			 LONGLISTJOBS},
 | |
| {{NULL, "magicequalsubst",    OPT_EMULATE},		 MAGICEQUALSUBST},
 | |
| {{NULL, "mailwarning",	      0},			 MAILWARNING},
 | |
| {{NULL, "markdirs",	      0},			 MARKDIRS},
 | |
| {{NULL, "menucomplete",	      0},			 MENUCOMPLETE},
 | |
| {{NULL, "monitor",	      OPT_SPECIAL},		 MONITOR},
 | |
| {{NULL, "multibyte",
 | |
| #ifdef MULTIBYTE_SUPPORT
 | |
| 			      OPT_ALL
 | |
| #else
 | |
| 			      0
 | |
| #endif
 | |
| 			      },			 MULTIBYTE},
 | |
| {{NULL, "multifuncdef",	      OPT_EMULATE|OPT_ZSH},	 MULTIFUNCDEF},
 | |
| {{NULL, "multios",	      OPT_EMULATE|OPT_ZSH},	 MULTIOS},
 | |
| {{NULL, "nomatch",	      OPT_EMULATE|OPT_NONBOURNE},NOMATCH},
 | |
| {{NULL, "notify",	      OPT_ZSH},			 NOTIFY},
 | |
| {{NULL, "nullglob",	      OPT_EMULATE},		 NULLGLOB},
 | |
| {{NULL, "numericglobsort",    OPT_EMULATE},		 NUMERICGLOBSORT},
 | |
| {{NULL, "octalzeroes",        OPT_EMULATE|OPT_SH},	 OCTALZEROES},
 | |
| {{NULL, "overstrike",	      0},			 OVERSTRIKE},
 | |
| {{NULL, "pathdirs",	      OPT_EMULATE},		 PATHDIRS},
 | |
| {{NULL, "pathscript",	      OPT_EMULATE|OPT_BOURNE},	 PATHSCRIPT},
 | |
| {{NULL, "pipefail",           OPT_EMULATE},              PIPEFAIL},
 | |
| {{NULL, "posixaliases",       OPT_EMULATE|OPT_BOURNE},	 POSIXALIASES},
 | |
| {{NULL, "posixargzero",       OPT_EMULATE},              POSIXARGZERO},
 | |
| {{NULL, "posixbuiltins",      OPT_EMULATE|OPT_BOURNE},	 POSIXBUILTINS},
 | |
| {{NULL, "posixcd",            OPT_EMULATE|OPT_BOURNE},	 POSIXCD},
 | |
| {{NULL, "posixidentifiers",   OPT_EMULATE|OPT_BOURNE},	 POSIXIDENTIFIERS},
 | |
| {{NULL, "posixjobs",          OPT_EMULATE|OPT_BOURNE},	 POSIXJOBS},
 | |
| {{NULL, "posixstrings",       OPT_EMULATE|OPT_BOURNE},   POSIXSTRINGS},
 | |
| {{NULL, "posixtraps",         OPT_EMULATE|OPT_BOURNE},	 POSIXTRAPS},
 | |
| {{NULL, "printeightbit",      0},                        PRINTEIGHTBIT},
 | |
| {{NULL, "printexitvalue",     0},			 PRINTEXITVALUE},
 | |
| {{NULL, "privileged",	      OPT_SPECIAL},		 PRIVILEGED},
 | |
| {{NULL, "promptbang",	      OPT_KSH},			 PROMPTBANG},
 | |
| {{NULL, "promptcr",	      OPT_ALL},			 PROMPTCR},
 | |
| {{NULL, "promptpercent",      OPT_NONBOURNE},		 PROMPTPERCENT},
 | |
| {{NULL, "promptsp",	      OPT_ALL},			 PROMPTSP},
 | |
| {{NULL, "promptsubst",	      OPT_BOURNE},		 PROMPTSUBST},
 | |
| {{NULL, "pushdignoredups",    OPT_EMULATE},		 PUSHDIGNOREDUPS},
 | |
| {{NULL, "pushdminus",	      OPT_EMULATE},		 PUSHDMINUS},
 | |
| {{NULL, "pushdsilent",	      0},			 PUSHDSILENT},
 | |
| {{NULL, "pushdtohome",	      OPT_EMULATE},		 PUSHDTOHOME},
 | |
| {{NULL, "rcexpandparam",      OPT_EMULATE},		 RCEXPANDPARAM},
 | |
| {{NULL, "rcquotes",	      OPT_EMULATE},		 RCQUOTES},
 | |
| {{NULL, "rcs",		      OPT_ALL},			 RCS},
 | |
| {{NULL, "recexact",	      0},			 RECEXACT},
 | |
| {{NULL, "rematchpcre",	      0},			 REMATCHPCRE},
 | |
| {{NULL, "restricted",	      OPT_SPECIAL},		 RESTRICTED},
 | |
| {{NULL, "rmstarsilent",	      OPT_BOURNE},		 RMSTARSILENT},
 | |
| {{NULL, "rmstarwait",	      0},			 RMSTARWAIT},
 | |
| {{NULL, "sharehistory",	      OPT_KSH},			 SHAREHISTORY},
 | |
| {{NULL, "shfileexpansion",    OPT_EMULATE|OPT_BOURNE},	 SHFILEEXPANSION},
 | |
| {{NULL, "shglob",	      OPT_EMULATE|OPT_BOURNE},	 SHGLOB},
 | |
| {{NULL, "shinstdin",	      OPT_SPECIAL},		 SHINSTDIN},
 | |
| {{NULL, "shnullcmd",          OPT_EMULATE|OPT_BOURNE},	 SHNULLCMD},
 | |
| {{NULL, "shoptionletters",    OPT_EMULATE|OPT_BOURNE},	 SHOPTIONLETTERS},
 | |
| {{NULL, "shortloops",	      OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS},
 | |
| {{NULL, "shwordsplit",	      OPT_EMULATE|OPT_BOURNE},	 SHWORDSPLIT},
 | |
| {{NULL, "singlecommand",      OPT_SPECIAL},		 SINGLECOMMAND},
 | |
| {{NULL, "singlelinezle",      OPT_KSH},			 SINGLELINEZLE},
 | |
| {{NULL, "sourcetrace",        0},			 SOURCETRACE},
 | |
| {{NULL, "sunkeyboardhack",    0},			 SUNKEYBOARDHACK},
 | |
| {{NULL, "transientrprompt",   0},			 TRANSIENTRPROMPT},
 | |
| {{NULL, "trapsasync",	      0},			 TRAPSASYNC},
 | |
| {{NULL, "typesetsilent",      OPT_EMULATE|OPT_BOURNE},	 TYPESETSILENT},
 | |
| {{NULL, "unset",	      OPT_EMULATE|OPT_BSHELL},	 UNSET},
 | |
| {{NULL, "verbose",	      0},			 VERBOSE},
 | |
| {{NULL, "vi",		      0},			 VIMODE},
 | |
| {{NULL, "warncreateglobal",   OPT_EMULATE},		 WARNCREATEGLOBAL},
 | |
| {{NULL, "xtrace",	      0},			 XTRACE},
 | |
| {{NULL, "zle",		      OPT_SPECIAL},		 USEZLE},
 | |
| {{NULL, "braceexpand",	      OPT_ALIAS}, /* ksh/bash */ -IGNOREBRACES},
 | |
| {{NULL, "dotglob",	      OPT_ALIAS}, /* bash */	 GLOBDOTS},
 | |
| {{NULL, "hashall",	      OPT_ALIAS}, /* bash */	 HASHCMDS},
 | |
| {{NULL, "histappend",	      OPT_ALIAS}, /* bash */	 APPENDHISTORY},
 | |
| {{NULL, "histexpand",	      OPT_ALIAS}, /* bash */	 BANGHIST},
 | |
| {{NULL, "log",		      OPT_ALIAS}, /* ksh */	 -HISTNOFUNCTIONS},
 | |
| {{NULL, "mailwarn",	      OPT_ALIAS}, /* bash */	 MAILWARNING},
 | |
| {{NULL, "onecmd",	      OPT_ALIAS}, /* bash */	 SINGLECOMMAND},
 | |
| {{NULL, "physical",	      OPT_ALIAS}, /* ksh/bash */ CHASELINKS},
 | |
| {{NULL, "promptvars",	      OPT_ALIAS}, /* bash */	 PROMPTSUBST},
 | |
| {{NULL, "stdin",	      OPT_ALIAS}, /* ksh */	 SHINSTDIN},
 | |
| {{NULL, "trackall",	      OPT_ALIAS}, /* ksh */	 HASHCMDS},
 | |
| {{NULL, "dvorak",	      0},			 DVORAK},
 | |
| {{NULL, NULL, 0}, 0}
 | |
| };
 | |
| 
 | |
| /* Option letters */
 | |
| 
 | |
| #define optletters (isset(SHOPTIONLETTERS) ? kshletters : zshletters)
 | |
| 
 | |
| #define FIRST_OPT '0'
 | |
| #define LAST_OPT 'y'
 | |
| 
 | |
| static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
 | |
|     /* 0 */  CORRECT,
 | |
|     /* 1 */  PRINTEXITVALUE,
 | |
|     /* 2 */ -BADPATTERN,
 | |
|     /* 3 */ -NOMATCH,
 | |
|     /* 4 */  GLOBDOTS,
 | |
|     /* 5 */  NOTIFY,
 | |
|     /* 6 */  BGNICE,
 | |
|     /* 7 */  IGNOREEOF,
 | |
|     /* 8 */  MARKDIRS,
 | |
|     /* 9 */  AUTOLIST,
 | |
|     /* : */  0,
 | |
|     /* ; */  0,
 | |
|     /* < */  0,
 | |
|     /* = */  0,
 | |
|     /* > */  0,
 | |
|     /* ? */  0,
 | |
|     /* @ */  0,
 | |
|     /* A */  0,			/* use with set for arrays */
 | |
|     /* B */ -BEEP,
 | |
|     /* C */ -CLOBBER,
 | |
|     /* D */  PUSHDTOHOME,
 | |
|     /* E */  PUSHDSILENT,
 | |
|     /* F */ -GLOBOPT,
 | |
|     /* G */  NULLGLOB,
 | |
|     /* H */  RMSTARSILENT,
 | |
|     /* I */  IGNOREBRACES,
 | |
|     /* J */  AUTOCD,
 | |
|     /* K */ -BANGHIST,
 | |
|     /* L */  SUNKEYBOARDHACK,
 | |
|     /* M */  SINGLELINEZLE,
 | |
|     /* N */  AUTOPUSHD,
 | |
|     /* O */  CORRECTALL,
 | |
|     /* P */  RCEXPANDPARAM,
 | |
|     /* Q */  PATHDIRS,
 | |
|     /* R */  LONGLISTJOBS,
 | |
|     /* S */  RECEXACT,
 | |
|     /* T */  CDABLEVARS,
 | |
|     /* U */  MAILWARNING,
 | |
|     /* V */ -PROMPTCR,
 | |
|     /* W */  AUTORESUME,
 | |
|     /* X */  LISTTYPES,
 | |
|     /* Y */  MENUCOMPLETE,
 | |
|     /* Z */  USEZLE,
 | |
|     /* [ */  0,
 | |
|     /* \ */  0,
 | |
|     /* ] */  0,
 | |
|     /* ^ */  0,
 | |
|     /* _ */  0,
 | |
|     /* ` */  0,
 | |
|     /* a */  ALLEXPORT,
 | |
|     /* b */  0,			/* in non-Bourne shells, end of options */
 | |
|     /* c */  0,			/* command follows */
 | |
|     /* d */ -GLOBALRCS,
 | |
|     /* e */  ERREXIT,
 | |
|     /* f */ -RCS,
 | |
|     /* g */  HISTIGNORESPACE,
 | |
|     /* h */  HISTIGNOREDUPS,
 | |
|     /* i */  INTERACTIVE,
 | |
|     /* j */  0,
 | |
|     /* k */  INTERACTIVECOMMENTS,
 | |
|     /* l */  LOGINSHELL,
 | |
|     /* m */  MONITOR,
 | |
|     /* n */ -EXECOPT,
 | |
|     /* o */  0,			/* long option name follows */
 | |
|     /* p */  PRIVILEGED,
 | |
|     /* q */  0,
 | |
|     /* r */  RESTRICTED,
 | |
|     /* s */  SHINSTDIN,
 | |
|     /* t */  SINGLECOMMAND,
 | |
|     /* u */ -UNSET,
 | |
|     /* v */  VERBOSE,
 | |
|     /* w */  CHASELINKS,
 | |
|     /* x */  XTRACE,
 | |
|     /* y */  SHWORDSPLIT,
 | |
| };
 | |
| 
 | |
| static short kshletters[LAST_OPT - FIRST_OPT + 1] = {
 | |
|     /* 0 */  0,
 | |
|     /* 1 */  0,
 | |
|     /* 2 */  0,
 | |
|     /* 3 */  0,
 | |
|     /* 4 */  0,
 | |
|     /* 5 */  0,
 | |
|     /* 6 */  0,
 | |
|     /* 7 */  0,
 | |
|     /* 8 */  0,
 | |
|     /* 9 */  0,
 | |
|     /* : */  0,
 | |
|     /* ; */  0,
 | |
|     /* < */  0,
 | |
|     /* = */  0,
 | |
|     /* > */  0,
 | |
|     /* ? */  0,
 | |
|     /* @ */  0,
 | |
|     /* A */  0,
 | |
|     /* B */  0,
 | |
|     /* C */ -CLOBBER,
 | |
|     /* D */  0,
 | |
|     /* E */  0,
 | |
|     /* F */  0,
 | |
|     /* G */  0,
 | |
|     /* H */  0,
 | |
|     /* I */  0,
 | |
|     /* J */  0,
 | |
|     /* K */  0,
 | |
|     /* L */  0,
 | |
|     /* M */  0,
 | |
|     /* N */  0,
 | |
|     /* O */  0,
 | |
|     /* P */  0,
 | |
|     /* Q */  0,
 | |
|     /* R */  0,
 | |
|     /* S */  0,
 | |
|     /* T */  TRAPSASYNC,
 | |
|     /* U */  0,
 | |
|     /* V */  0,
 | |
|     /* W */  0,
 | |
|     /* X */  MARKDIRS,
 | |
|     /* Y */  0,
 | |
|     /* Z */  0,
 | |
|     /* [ */  0,
 | |
|     /* \ */  0,
 | |
|     /* ] */  0,
 | |
|     /* ^ */  0,
 | |
|     /* _ */  0,
 | |
|     /* ` */  0,
 | |
|     /* a */  ALLEXPORT,
 | |
|     /* b */  NOTIFY,
 | |
|     /* c */  0,
 | |
|     /* d */  0,
 | |
|     /* e */  ERREXIT,
 | |
|     /* f */ -GLOBOPT,
 | |
|     /* g */  0,
 | |
|     /* h */  0,
 | |
|     /* i */  INTERACTIVE,
 | |
|     /* j */  0,
 | |
|     /* k */  0,
 | |
|     /* l */  LOGINSHELL,
 | |
|     /* m */  MONITOR,
 | |
|     /* n */ -EXECOPT,
 | |
|     /* o */  0,
 | |
|     /* p */  PRIVILEGED,
 | |
|     /* q */  0,
 | |
|     /* r */  RESTRICTED,
 | |
|     /* s */  SHINSTDIN,
 | |
|     /* t */  SINGLECOMMAND,
 | |
|     /* u */ -UNSET,
 | |
|     /* v */  VERBOSE,
 | |
|     /* w */  0,
 | |
|     /* x */  XTRACE,
 | |
|     /* y */  0,
 | |
| };
 | |
| 
 | |
| /* Initialisation of the option name hash table */
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| printoptionnode(HashNode hn, int set)
 | |
| {
 | |
|     Optname on = (Optname) hn;
 | |
|     int optno = on->optno;
 | |
| 
 | |
|     if (optno < 0)
 | |
| 	optno = -optno;
 | |
|     if (isset(KSHOPTIONPRINT)) {
 | |
| 	if (defset(on, emulation))
 | |
| 	    printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
 | |
| 	else
 | |
| 	    printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
 | |
|     } else if (set == (isset(optno) ^ defset(on, emulation))) {
 | |
| 	if (set ^ isset(optno))
 | |
| 	    fputs("no", stdout);
 | |
| 	puts(on->node.nam);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**/
 | |
| void
 | |
| createoptiontable(void)
 | |
| {
 | |
|     Optname on;
 | |
| 
 | |
|     optiontab = newhashtable(101, "optiontab", NULL);
 | |
| 
 | |
|     optiontab->hash        = hasher;
 | |
|     optiontab->emptytable  = NULL;
 | |
|     optiontab->filltable   = NULL;
 | |
|     optiontab->cmpnodes    = strcmp;
 | |
|     optiontab->addnode     = addhashnode;
 | |
|     optiontab->getnode     = gethashnode;
 | |
|     optiontab->getnode2    = gethashnode2;
 | |
|     optiontab->removenode  = NULL;
 | |
|     optiontab->disablenode = disablehashnode;
 | |
|     optiontab->enablenode  = enablehashnode;
 | |
|     optiontab->freenode    = NULL;
 | |
|     optiontab->printnode   = printoptionnode;
 | |
| 
 | |
|     for (on = optns; on->node.nam; on++)
 | |
| 	optiontab->addnode(optiontab, on->node.nam, on);
 | |
| }
 | |
| 
 | |
| /* Emulation appropriate to the setemulate function */
 | |
| 
 | |
| static int setemulate_emulation;
 | |
| 
 | |
| /* Option array manipulated within the setemulate function */
 | |
| 
 | |
| /**/
 | |
| static char *setemulate_opts;
 | |
| 
 | |
| /* Setting of default options */
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| setemulate(HashNode hn, int fully)
 | |
| {
 | |
|     Optname on = (Optname) hn;
 | |
| 
 | |
|     /* Set options: each non-special option is set according to the *
 | |
|      * current emulation mode if either it is considered relevant   *
 | |
|      * to emulation or we are doing a full emulation (as indicated  *
 | |
|      * by the `fully' parameter).                                   */
 | |
|     if (!(on->node.flags & OPT_ALIAS) &&
 | |
| 	((fully && !(on->node.flags & OPT_SPECIAL)) ||
 | |
| 	 (on->node.flags & OPT_EMULATE)))
 | |
| 	setemulate_opts[on->optno] = defset(on, setemulate_emulation);
 | |
| }
 | |
| 
 | |
| /**/
 | |
| void
 | |
| installemulation(int new_emulation, char *new_opts)
 | |
| {
 | |
|     setemulate_emulation = new_emulation;
 | |
|     setemulate_opts = new_opts;
 | |
|     scanhashtable(optiontab, 0, 0, 0, setemulate,
 | |
| 		  !!(new_emulation & EMULATE_FULLY));
 | |
| }
 | |
| 
 | |
| /**/
 | |
| void
 | |
| emulate(const char *zsh_name, int fully, int *new_emulation, char *new_opts)
 | |
| {
 | |
|     char ch = *zsh_name;
 | |
| 
 | |
|     if (ch == 'r')
 | |
| 	ch = zsh_name[1];
 | |
| 
 | |
|     /* Work out the new emulation mode */
 | |
|     if (ch == 'c')
 | |
| 	*new_emulation = EMULATE_CSH;
 | |
|     else if (ch == 'k')
 | |
| 	*new_emulation = EMULATE_KSH;
 | |
|     else if (ch == 's' || ch == 'b')
 | |
| 	*new_emulation = EMULATE_SH;
 | |
|     else
 | |
| 	*new_emulation = EMULATE_ZSH;
 | |
| 
 | |
|     if (fully)
 | |
| 	*new_emulation |= EMULATE_FULLY;
 | |
|     installemulation(*new_emulation, new_opts);
 | |
| 
 | |
|     if (funcstack && funcstack->tp == FS_FUNC) {
 | |
| 	/*
 | |
| 	 * We are inside a function.  Decide if it's traced.
 | |
| 	 * Pedantic note: the function in the function table isn't
 | |
| 	 * guaranteed to be what we're executing, but it's
 | |
| 	 * close enough.
 | |
| 	 */
 | |
| 	Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name);
 | |
| 	if (shf && (shf->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL))) {
 | |
| 	    /* Tracing is on, so set xtrace */
 | |
| 	    new_opts[XTRACE] = 1;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* setopt, unsetopt */
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| setoption(HashNode hn, int value)
 | |
| {
 | |
|     dosetopt(((Optname) hn)->optno, value, 0, opts);
 | |
| }
 | |
| 
 | |
| /**/
 | |
| int
 | |
| bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
 | |
| {
 | |
|     int action, optno, match = 0;
 | |
| 
 | |
|     /* With no arguments or options, display options. */
 | |
|     if (!*args) {
 | |
| 	scanhashtable(optiontab, 1, 0, OPT_ALIAS, optiontab->printnode, !isun);
 | |
| 	return 0;
 | |
|     }
 | |
| 
 | |
|     /* loop through command line options (begins with "-" or "+") */
 | |
|     while (*args && (**args == '-' || **args == '+')) {
 | |
| 	action = (**args == '-') ^ isun;
 | |
| 	if(!args[0][1])
 | |
| 	    *args = "--";
 | |
| 	while (*++*args) {
 | |
| 	    if(**args == Meta)
 | |
| 		*++*args ^= 32;
 | |
| 	    /* The pseudo-option `--' signifies the end of options. */
 | |
| 	    if (**args == '-') {
 | |
| 		args++;
 | |
| 		goto doneoptions;
 | |
| 	    } else if (**args == 'o') {
 | |
| 		if (!*++*args)
 | |
| 		    args++;
 | |
| 		if (!*args) {
 | |
| 		    zwarnnam(nam, "string expected after -o");
 | |
| 		    inittyptab();
 | |
| 		    return 1;
 | |
| 		}
 | |
| 		if(!(optno = optlookup(*args)))
 | |
| 		    zwarnnam(nam, "no such option: %s", *args);
 | |
| 		else if(dosetopt(optno, action, 0, opts))
 | |
| 		    zwarnnam(nam, "can't change option: %s", *args);
 | |
| 		break;
 | |
| 	    } else if(**args == 'm') {
 | |
| 		match = 1;
 | |
| 	    } else {
 | |
| 	    	if (!(optno = optlookupc(**args)))
 | |
| 		    zwarnnam(nam, "bad option: -%c", **args);
 | |
| 		else if(dosetopt(optno, action, 0, opts))
 | |
| 		    zwarnnam(nam, "can't change option: -%c", **args);
 | |
| 	    }
 | |
| 	}
 | |
| 	args++;
 | |
|     }
 | |
|     doneoptions:
 | |
| 
 | |
|     if (!match) {
 | |
| 	/* Not globbing the arguments -- arguments are simply option names. */
 | |
| 	while (*args) {
 | |
| 	    if(!(optno = optlookup(*args++)))
 | |
| 		zwarnnam(nam, "no such option: %s", args[-1]);
 | |
| 	    else if(dosetopt(optno, !isun, 0, opts))
 | |
| 		zwarnnam(nam, "can't change option: %s", args[-1]);
 | |
| 	}
 | |
|     } else {
 | |
| 	/* Globbing option (-m) set. */
 | |
| 	while (*args) {
 | |
| 	    Patprog pprog;
 | |
| 	    char *s, *t;
 | |
| 
 | |
| 	    t = s = dupstring(*args);
 | |
| 	    while (*t)
 | |
| 		if (*t == '_')
 | |
| 		    chuck(t);
 | |
| 		else {
 | |
| 		    /* See comment in optlookup() */
 | |
| 		    if (*t >= 'A' && *t <= 'Z')
 | |
| 			*t = (*t - 'A') + 'a';
 | |
| 		    t++;
 | |
| 		}
 | |
| 
 | |
| 	    /* Expand the current arg. */
 | |
| 	    tokenize(s);
 | |
| 	    if (!(pprog = patcompile(s, PAT_STATIC, NULL))) {
 | |
| 		zwarnnam(nam, "bad pattern: %s", *args);
 | |
| 		continue;
 | |
| 	    }
 | |
| 	    /* Loop over expansions. */
 | |
| 	    scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
 | |
| 			   setoption, !isun);
 | |
| 	    args++;
 | |
| 	}
 | |
|     }
 | |
|     inittyptab();
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| /* Identify an option name */
 | |
| 
 | |
| /**/
 | |
| mod_export int
 | |
| optlookup(char const *name)
 | |
| {
 | |
|     char *s, *t;
 | |
|     Optname n;
 | |
| 
 | |
|     s = t = dupstring(name);
 | |
| 
 | |
|     /* exorcise underscores, and change to lowercase */
 | |
|     while (*t)
 | |
| 	if (*t == '_')
 | |
| 	    chuck(t);
 | |
| 	else {
 | |
| 	    /*
 | |
| 	     * Some locales (in particular tr_TR.UTF-8) may
 | |
| 	     * have non-standard mappings of ASCII characters,
 | |
| 	     * so be careful.  Option names must be ASCII so
 | |
| 	     * we don't need to be too clever.
 | |
| 	     */
 | |
| 	    if (*t >= 'A' && *t <= 'Z')
 | |
| 		*t = (*t - 'A') + 'a';
 | |
| 	    t++;
 | |
| 	}
 | |
| 
 | |
|     /* look up name in the table */
 | |
|     if (s[0] == 'n' && s[1] == 'o' &&
 | |
| 	(n = (Optname) optiontab->getnode(optiontab, s + 2))) {
 | |
| 	return -n->optno;
 | |
|     } else if ((n = (Optname) optiontab->getnode(optiontab, s)))
 | |
| 	return n->optno;
 | |
|     else
 | |
| 	return OPT_INVALID;
 | |
| }
 | |
| 
 | |
| /* Identify an option letter */
 | |
| 
 | |
| /**/
 | |
| int
 | |
| optlookupc(char c)
 | |
| {
 | |
|     if(c < FIRST_OPT || c > LAST_OPT)
 | |
| 	return 0;
 | |
| 
 | |
|     return optletters[c - FIRST_OPT];
 | |
| }
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| restrictparam(char *nam)
 | |
| {
 | |
|     Param pm = (Param) paramtab->getnode(paramtab, nam);
 | |
| 
 | |
|     if (pm) {
 | |
| 	pm->node.flags |= PM_SPECIAL | PM_RESTRICTED;
 | |
| 	return;
 | |
|     }
 | |
|     createparam(nam, PM_SCALAR | PM_UNSET | PM_SPECIAL | PM_RESTRICTED);
 | |
| }
 | |
| 
 | |
| /* list of restricted parameters which are not otherwise special */
 | |
| static char *rparams[] = {
 | |
|     "SHELL", "HISTFILE", "LD_LIBRARY_PATH", "LD_AOUT_LIBRARY_PATH",
 | |
|     "LD_PRELOAD", "LD_AOUT_PRELOAD", NULL
 | |
| };
 | |
| 
 | |
| /* Set or unset an option, as a result of user request.  The option *
 | |
|  * number may be negative, indicating that the sense is reversed    *
 | |
|  * from the usual meaning of the option.                            */
 | |
| 
 | |
| /**/
 | |
| mod_export int
 | |
| dosetopt(int optno, int value, int force, char *new_opts)
 | |
| {
 | |
|     if(!optno)
 | |
| 	return -1;
 | |
|     if(optno < 0) {
 | |
| 	optno = -optno;
 | |
| 	value = !value;
 | |
|     }
 | |
|     if (optno == RESTRICTED) {
 | |
| 	if (isset(RESTRICTED))
 | |
| 	    return value ? 0 : -1;
 | |
| 	if (value) {
 | |
| 	    char **s;
 | |
| 
 | |
| 	    for (s = rparams; *s; s++)
 | |
| 		restrictparam(*s);
 | |
| 	}
 | |
|     } else if(!force && optno == EXECOPT && !value && interact) {
 | |
| 	/* cannot set noexec when interactive */
 | |
| 	return -1;
 | |
|     } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
 | |
| 	    optno == SINGLECOMMAND)) {
 | |
| 	if (new_opts[optno] == value)
 | |
| 	    return 0;
 | |
| 	/* it is not permitted to change the value of these options */
 | |
| 	return -1;
 | |
|     } else if(!force && optno == USEZLE && value) {
 | |
| 	/* we require a terminal in order to use ZLE */
 | |
| 	if(!interact || SHTTY == -1 || !shout)
 | |
| 	    return -1;
 | |
|     } else if(optno == PRIVILEGED && !value) {
 | |
| 	/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
 | |
| #ifdef HAVE_SETUID
 | |
| 	setuid(getuid());
 | |
| 	setgid(getgid());
 | |
|         if (setuid(getuid())) {
 | |
|             zwarn("failed to change user ID: %e", errno);
 | |
|             return -1;
 | |
| 	} else if (setgid(getgid())) {
 | |
|             zwarn("failed to change group ID: %e", errno);
 | |
|             return -1;
 | |
|         }
 | |
| #else
 | |
|         zwarn("setuid not available");
 | |
|         return -1;
 | |
| #endif /* not HAVE_SETUID */
 | |
| #ifdef JOB_CONTROL
 | |
|     } else if (!force && optno == MONITOR && value) {
 | |
| 	if (new_opts[optno] == value)
 | |
| 	    return 0;
 | |
| 	if (SHTTY != -1) {
 | |
| 	    origpgrp = GETPGRP();
 | |
| 	    acquire_pgrp();
 | |
| 	} else
 | |
| 	    return -1;
 | |
| #else
 | |
|     } else if(optno == MONITOR && value) {
 | |
| 	    return -1;
 | |
| #endif /* not JOB_CONTROL */
 | |
| #ifdef GETPWNAM_FAKED
 | |
|     } else if(optno == CDABLEVARS && value) {
 | |
| 	    return -1;
 | |
| #endif /* GETPWNAM_FAKED */
 | |
|     } else if ((optno == EMACSMODE || optno == VIMODE) && value) {
 | |
| 	if (sticky && sticky->emulation)
 | |
| 	    return -1;
 | |
| 	zleentry(ZLE_CMD_SET_KEYMAP, optno);
 | |
| 	new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
 | |
|     } else if (optno == SUNKEYBOARDHACK) {
 | |
| 	/* for backward compatibility */
 | |
| 	keyboardhackchar = (value ? '`' : '\0');
 | |
|     }
 | |
|     new_opts[optno] = value;
 | |
|     if (optno == BANGHIST || optno == SHINSTDIN)
 | |
| 	inittyptab();
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| /* Function to get value for special parameter `-' */
 | |
| 
 | |
| /**/
 | |
| char *
 | |
| dashgetfn(UNUSED(Param pm))
 | |
| {
 | |
|     static char buf[LAST_OPT - FIRST_OPT + 2];
 | |
|     char *val = buf;
 | |
|     int i;
 | |
| 
 | |
|     for(i = 0; i <= LAST_OPT - FIRST_OPT; i++) {
 | |
| 	int optno = optletters[i];
 | |
| 	if(optno && ((optno > 0) ? isset(optno) : unset(-optno)))
 | |
| 	    *val++ = FIRST_OPT + i;
 | |
|     }
 | |
|     *val = '\0';
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| /* print options for set -o/+o */
 | |
| 
 | |
| /**/
 | |
| void
 | |
| printoptionstates(int hadplus)
 | |
| {
 | |
|     scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionnodestate, hadplus);
 | |
| }
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| printoptionnodestate(HashNode hn, int hadplus)
 | |
| {
 | |
|     Optname on = (Optname) hn;
 | |
|     int optno = on->optno;
 | |
| 
 | |
|     if (hadplus) {
 | |
| 	printf("set %co %s%s\n",
 | |
| 	       defset(on, emulation) != isset(optno) ? '-' : '+',
 | |
| 	       defset(on, emulation) ? "no" : "",
 | |
| 	       on->node.nam);
 | |
|     } else {
 | |
| 	if (defset(on, emulation))
 | |
| 	    printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
 | |
| 	else
 | |
| 	    printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* Print option list for --help */
 | |
| 
 | |
| /**/
 | |
| void
 | |
| printoptionlist(void)
 | |
| {
 | |
|     short *lp;
 | |
|     char c;
 | |
| 
 | |
|     printf("\nNamed options:\n");
 | |
|     scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0);
 | |
|     printf("\nOption aliases:\n");
 | |
|     scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0);
 | |
|     printf("\nOption letters:\n");
 | |
|     for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) {
 | |
| 	if(!*lp)
 | |
| 	    continue;
 | |
| 	printf("  -%c  ", c);
 | |
| 	printoptionlist_printequiv(*lp);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| printoptionlist_printoption(HashNode hn, UNUSED(int ignored))
 | |
| {
 | |
|     Optname on = (Optname) hn;
 | |
| 
 | |
|     if(on->node.flags & OPT_ALIAS) {
 | |
| 	printf("  --%-19s  ", on->node.nam);
 | |
| 	printoptionlist_printequiv(on->optno);
 | |
|     } else
 | |
| 	printf("  --%s\n", on->node.nam);
 | |
| }
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| printoptionlist_printequiv(int optno)
 | |
| {
 | |
|     int isneg = optno < 0;
 | |
| 
 | |
|     optno *= (isneg ? -1 : 1);
 | |
|     printf("  equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].node.nam);
 | |
| }
 | |
| 
 | |
| /**/
 | |
| static char *print_emulate_opts;
 | |
| 
 | |
| /**/
 | |
| static void
 | |
| print_emulate_option(HashNode hn, int fully)
 | |
| {
 | |
|     Optname on = (Optname) hn;
 | |
| 
 | |
|     if (!(on->node.flags & OPT_ALIAS) &&
 | |
| 	((fully && !(on->node.flags & OPT_SPECIAL)) ||
 | |
| 	 (on->node.flags & OPT_EMULATE)))
 | |
|     {
 | |
| 	if (!print_emulate_opts[on->optno])
 | |
| 	    fputs("no", stdout);
 | |
| 	puts(on->node.nam);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * List the settings of options associated with an emulation
 | |
|  */
 | |
| 
 | |
| /**/
 | |
| void list_emulate_options(char *cmdopts, int fully)
 | |
| {
 | |
|     print_emulate_opts = cmdopts;
 | |
|     scanhashtable(optiontab, 1, 0, 0, print_emulate_option, fully);
 | |
| }
 |