version 1.1.1.1, 1996/09/21 05:39:43 |
version 1.1.1.2, 2003/04/13 18:21:21 |
|
|
/* |
/* |
* Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman |
* Copyright (C) 1984-2002 Mark Nudelman |
* All rights reserved. |
|
* |
* |
* Redistribution and use in source and binary forms, with or without |
* You may distribute under the terms of either the GNU General Public |
* modification, are permitted provided that the following conditions |
* License or the Less License, as specified in the README file. |
* 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 in the documentation and/or other materials provided with |
|
* the distribution. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY |
* For more information about less, or for information on how to |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* contact the author, see the README file. |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. |
|
*/ |
*/ |
|
|
|
|
|
|
public int bs_mode; /* How to process backspaces */ |
public int bs_mode; /* How to process backspaces */ |
public int know_dumb; /* Don't complain about dumb terminals */ |
public int know_dumb; /* Don't complain about dumb terminals */ |
public int quit_at_eof; /* Quit after hitting end of file twice */ |
public int quit_at_eof; /* Quit after hitting end of file twice */ |
|
public int quit_if_one_screen; /* Quit if EOF on first screen */ |
public int squeeze; /* Squeeze multiple blank lines into one */ |
public int squeeze; /* Squeeze multiple blank lines into one */ |
public int tabstop; /* Tab settings */ |
public int tabstop; /* Tab settings */ |
public int back_scroll; /* Repaint screen on backwards movement */ |
public int back_scroll; /* Repaint screen on backwards movement */ |
public int forw_scroll; /* Repaint screen on forward movement */ |
public int forw_scroll; /* Repaint screen on forward movement */ |
public int twiddle; /* Display "~" for lines after EOF */ |
|
public int caseless; /* Do "caseless" searches */ |
public int caseless; /* Do "caseless" searches */ |
public int linenums; /* Use line numbers */ |
public int linenums; /* Use line numbers */ |
public int cbufs; /* Current number of buffers */ |
|
public int autobuf; /* Automatically allocate buffers as needed */ |
public int autobuf; /* Automatically allocate buffers as needed */ |
public int nohelp; /* Disable the HELP command */ |
public int bufspace; /* Max buffer space per file (K) */ |
public int ctldisp; /* Send control chars to screen untranslated */ |
public int ctldisp; /* Send control chars to screen untranslated */ |
public int force_open; /* Open the file even if not regular file */ |
public int force_open; /* Open the file even if not regular file */ |
public int swindow; /* Size of scrolling window */ |
public int swindow; /* Size of scrolling window */ |
public int jump_sline; /* Screen line of "jump target" */ |
public int jump_sline; /* Screen line of "jump target" */ |
public int chopline; /* Truncate displayed lines at screen width */ |
public int chopline; /* Truncate displayed lines at screen width */ |
public int no_init; /* Disable sending ti/te termcap strings */ |
public int no_init; /* Disable sending ti/te termcap strings */ |
|
public int no_keypad; /* Disable sending ks/ke termcap strings */ |
|
public int twiddle; /* Show tildes after EOF */ |
|
public int show_attn; /* Hilite first unread line */ |
|
public int shift_count; /* Number of positions to shift horizontally */ |
|
public int status_col; /* Display a status column */ |
|
public int use_lessopen; /* Use the LESSOPEN filter */ |
#if HILITE_SEARCH |
#if HILITE_SEARCH |
public int hilite_search; /* Highlight matched search patterns? */ |
public int hilite_search; /* Highlight matched search patterns? */ |
#endif |
#endif |
|
|
/* |
/* |
|
* Long option names. |
|
*/ |
|
static struct optname a_optname = { "search-skip-screen", NULL }; |
|
static struct optname b_optname = { "buffers", NULL }; |
|
static struct optname B__optname = { "auto-buffers", NULL }; |
|
static struct optname c_optname = { "clear-screen", NULL }; |
|
static struct optname d_optname = { "dumb", NULL }; |
|
#if MSDOS_COMPILER |
|
static struct optname D__optname = { "color", NULL }; |
|
#endif |
|
static struct optname e_optname = { "quit-at-eof", NULL }; |
|
static struct optname f_optname = { "force", NULL }; |
|
static struct optname F__optname = { "quit-if-one-screen", NULL }; |
|
#if HILITE_SEARCH |
|
static struct optname g_optname = { "hilite-search", NULL }; |
|
#endif |
|
static struct optname h_optname = { "max-back-scroll", NULL }; |
|
static struct optname i_optname = { "ignore-case", NULL }; |
|
static struct optname j_optname = { "jump-target", NULL }; |
|
static struct optname J__optname = { "status-column", NULL }; |
|
#if USERFILE |
|
static struct optname k_optname = { "lesskey-file", NULL }; |
|
#endif |
|
static struct optname L__optname = { "no-lessopen", NULL }; |
|
static struct optname m_optname = { "long-prompt", NULL }; |
|
static struct optname n_optname = { "line-numbers", NULL }; |
|
#if LOGFILE |
|
static struct optname o_optname = { "log-file", NULL }; |
|
static struct optname O__optname = { "LOG-FILE", NULL }; |
|
#endif |
|
static struct optname p_optname = { "pattern", NULL }; |
|
static struct optname P__optname = { "prompt", NULL }; |
|
static struct optname q2_optname = { "silent", NULL }; |
|
static struct optname q_optname = { "quiet", &q2_optname }; |
|
static struct optname r_optname = { "raw-control-chars", NULL }; |
|
static struct optname s_optname = { "squeeze-blank-lines", NULL }; |
|
static struct optname S__optname = { "chop-long-lines", NULL }; |
|
#if TAGS |
|
static struct optname t_optname = { "tag", NULL }; |
|
static struct optname T__optname = { "tag-file", NULL }; |
|
#endif |
|
static struct optname u_optname = { "underline-special", NULL }; |
|
static struct optname V__optname = { "version", NULL }; |
|
static struct optname w_optname = { "hilite-unread", NULL }; |
|
static struct optname x_optname = { "tabs", NULL }; |
|
static struct optname X__optname = { "no-init", NULL }; |
|
static struct optname y_optname = { "max-forw-scroll", NULL }; |
|
static struct optname z_optname = { "window", NULL }; |
|
static struct optname quote_optname = { "quotes", NULL }; |
|
static struct optname tilde_optname = { "tilde", NULL }; |
|
static struct optname query_optname = { "help", NULL }; |
|
static struct optname pound_optname = { "shift", NULL }; |
|
static struct optname keypad_optname = { "no-keypad", NULL }; |
|
|
|
|
|
/* |
* Table of all options and their semantics. |
* Table of all options and their semantics. |
|
* |
|
* For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are |
|
* the description of the option when set to 0, 1 or 2, respectively. |
|
* For NUMBER options, odesc[0] is the prompt to use when entering |
|
* a new value, and odesc[1] is the description, which should contain |
|
* one %d which is replaced by the value of the number. |
|
* For STRING options, odesc[0] is the prompt to use when entering |
|
* a new value, and odesc[1], if not NULL, is the set of characters |
|
* that are valid in the string. |
*/ |
*/ |
static struct option option[] = |
static struct loption option[] = |
{ |
{ |
{ 'a', BOOL, OPT_OFF, &how_search, NULL, |
{ 'a', &a_optname, |
"Search includes displayed screen", |
BOOL, OPT_OFF, &how_search, NULL, |
"Search skips displayed screen", |
{ |
NULL |
"Search includes displayed screen", |
|
"Search skips displayed screen", |
|
NULL |
|
} |
}, |
}, |
{ 'b', NUMBER, 10, &cbufs, opt_b, |
|
"Buffers: ", |
{ 'b', &b_optname, |
"%d buffers", |
NUMBER|INIT_HANDLER, 64, &bufspace, opt_b, |
NULL |
{ |
|
"Max buffer space per file (K): ", |
|
"Max buffer space per file: %dK", |
|
NULL |
|
} |
}, |
}, |
{ 'B', BOOL, OPT_ON, &autobuf, NULL, |
{ 'B', &B__optname, |
"Don't automatically allocate buffers", |
BOOL, OPT_ON, &autobuf, NULL, |
"Automatically allocate buffers when needed", |
{ |
NULL |
"Don't automatically allocate buffers", |
|
"Automatically allocate buffers when needed", |
|
NULL |
|
} |
}, |
}, |
{ 'c', TRIPLE, OPT_OFF, &top_scroll, NULL, |
{ 'c', &c_optname, |
"Repaint by scrolling from bottom of screen", |
TRIPLE, OPT_OFF, &top_scroll, NULL, |
"Repaint by clearing each line", |
{ |
"Repaint by painting from top of screen" |
"Repaint by scrolling from bottom of screen", |
|
"Repaint by clearing each line", |
|
"Repaint by painting from top of screen" |
|
} |
}, |
}, |
{ 'd', BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL, |
{ 'd', &d_optname, |
"Assume intelligent terminal", |
BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL, |
"Assume dumb terminal", |
{ |
NULL |
"Assume intelligent terminal", |
|
"Assume dumb terminal", |
|
NULL |
|
} |
}, |
}, |
#if MSOFTC |
#if MSDOS_COMPILER |
{ 'D', STRING|REPAINT, 0, NULL, opt_D, |
{ 'D', &D__optname, |
"color desc: ", NULL, NULL |
STRING|REPAINT|NO_QUERY, 0, NULL, opt_D, |
|
{ |
|
"color desc: ", |
|
"Ddknsu0123456789.", |
|
NULL |
|
} |
}, |
}, |
#endif |
#endif |
{ 'e', TRIPLE, OPT_OFF, &quit_at_eof, NULL, |
{ 'e', &e_optname, |
"Don't quit at end-of-file", |
TRIPLE, OPT_OFF, &quit_at_eof, NULL, |
"Quit at end-of-file", |
{ |
"Quit immediately at end-of-file" |
"Don't quit at end-of-file", |
|
"Quit at end-of-file", |
|
"Quit immediately at end-of-file" |
|
} |
}, |
}, |
{ 'f', BOOL, OPT_OFF, &force_open, NULL, |
{ 'f', &f_optname, |
"Open only regular files", |
BOOL, OPT_OFF, &force_open, NULL, |
"Open even non-regular files", |
{ |
NULL |
"Open only regular files", |
|
"Open even non-regular files", |
|
NULL |
|
} |
}, |
}, |
|
{ 'F', &F__optname, |
|
BOOL, OPT_OFF, &quit_if_one_screen, NULL, |
|
{ |
|
"Don't quit if end-of-file on first screen", |
|
"Quit if end-of-file on first screen", |
|
NULL |
|
} |
|
}, |
#if HILITE_SEARCH |
#if HILITE_SEARCH |
{ 'g', TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL, |
{ 'g', &g_optname, |
"Don't highlight search matches", |
TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL, |
"Highlight matches for previous search only", |
{ |
"Highlight all matches for previous search pattern", |
"Don't highlight search matches", |
|
"Highlight matches for previous search only", |
|
"Highlight all matches for previous search pattern", |
|
} |
}, |
}, |
#endif |
#endif |
{ 'h', NUMBER, -1, &back_scroll, NULL, |
{ 'h', &h_optname, |
"Backwards scroll limit: ", |
NUMBER, -1, &back_scroll, NULL, |
"Backwards scroll limit is %d lines", |
{ |
NULL |
"Backwards scroll limit: ", |
|
"Backwards scroll limit is %d lines", |
|
NULL |
|
} |
}, |
}, |
{ 'H', BOOL|NO_TOGGLE, OPT_OFF, &nohelp, NULL, |
{ 'i', &i_optname, |
"Allow help command", |
TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i, |
"Don't allow help command", |
{ |
NULL |
"Case is significant in searches", |
|
"Ignore case in searches", |
|
"Ignore case in searches and in patterns" |
|
} |
}, |
}, |
{ 'i', TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i, |
{ 'j', &j_optname, |
"Case is significant in searches", |
NUMBER, 1, &jump_sline, NULL, |
"Ignore case in searches", |
{ |
"Ignore case in searches and in patterns" |
"Target line: ", |
|
"Position target at screen line %d", |
|
NULL |
|
} |
}, |
}, |
{ 'j', NUMBER, 1, &jump_sline, NULL, |
{ 'J', &J__optname, |
"Target line: ", |
BOOL|REPAINT, OPT_OFF, &status_col, NULL, |
"Position target at screen line %d", |
{ |
NULL |
"Don't display a status column", |
|
"Display a status column", |
|
NULL |
|
} |
}, |
}, |
#if USERFILE |
#if USERFILE |
{ 'k', STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k, |
{ 'k', &k_optname, |
NULL, NULL, NULL |
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k, |
|
{ NULL, NULL, NULL } |
}, |
}, |
#endif |
#endif |
{ 'l', STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_l, |
{ 'l', NULL, |
NULL, NULL, NULL |
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_l, |
|
{ NULL, NULL, NULL } |
}, |
}, |
{ 'm', TRIPLE, OPT_OFF, &pr_type, NULL, |
{ 'L', &L__optname, |
"Short prompt", |
BOOL, OPT_ON, &use_lessopen, NULL, |
"Medium prompt", |
{ |
"Long prompt" |
"Don't use the LESSOPEN filter", |
|
"Use the LESSOPEN filter", |
|
NULL |
|
} |
}, |
}, |
{ 'n', TRIPLE|REPAINT, OPT_ON, &linenums, NULL, |
{ 'm', &m_optname, |
"Don't use line numbers", |
TRIPLE, OPT_OFF, &pr_type, NULL, |
"Use line numbers", |
{ |
"Constantly display line numbers" |
"Short prompt", |
|
"Medium prompt", |
|
"Long prompt" |
|
} |
}, |
}, |
|
{ 'n', &n_optname, |
|
TRIPLE|REPAINT, OPT_ON, &linenums, NULL, |
|
{ |
|
"Don't use line numbers", |
|
"Use line numbers", |
|
"Constantly display line numbers" |
|
} |
|
}, |
#if LOGFILE |
#if LOGFILE |
{ 'o', STRING, 0, NULL, opt_o, |
{ 'o', &o_optname, |
"log file: ", NULL, NULL |
STRING, 0, NULL, opt_o, |
|
{ "log file: ", NULL, NULL } |
}, |
}, |
{ 'O', STRING, 0, NULL, opt__O, |
{ 'O', &O__optname, |
"Log file: ", NULL, NULL |
STRING, 0, NULL, opt__O, |
|
{ "Log file: ", NULL, NULL } |
}, |
}, |
#endif |
#endif |
{ 'p', STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p, |
{ 'p', &p_optname, |
NULL, NULL, NULL |
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p, |
|
{ NULL, NULL, NULL } |
}, |
}, |
{ 'P', STRING, 0, NULL, opt__P, |
{ 'P', &P__optname, |
"prompt: ", NULL, NULL |
STRING, 0, NULL, opt__P, |
|
{ "prompt: ", NULL, NULL } |
}, |
}, |
{ 'q', TRIPLE, OPT_OFF, &quiet, NULL, |
{ 'q', &q_optname, |
"Ring the bell for errors AND at eof/bof", |
TRIPLE, OPT_OFF, &quiet, NULL, |
"Ring the bell for errors but not at eof/bof", |
{ |
"Never ring the bell" |
"Ring the bell for errors AND at eof/bof", |
|
"Ring the bell for errors but not at eof/bof", |
|
"Never ring the bell" |
|
} |
}, |
}, |
{ 'r', BOOL|REPAINT, OPT_ON, &ctldisp, NULL, |
{ 'r', &r_optname, |
"Display control characters directly", |
TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL, |
"Display control characters as ^X", |
{ |
NULL |
"Display control characters as ^X", |
|
"Display control characters directly", |
|
"Display control characters directly, processing ANSI sequences" |
|
} |
}, |
}, |
{ 's', BOOL|REPAINT, OPT_OFF, &squeeze, NULL, |
{ 's', &s_optname, |
"Display all blank lines", |
BOOL|REPAINT, OPT_OFF, &squeeze, NULL, |
"Squeeze multiple blank lines", |
{ |
NULL |
"Display all blank lines", |
|
"Squeeze multiple blank lines", |
|
NULL |
|
} |
}, |
}, |
{ 'S', BOOL|REPAINT, OPT_OFF, &chopline, NULL, |
{ 'S', &S__optname, |
"Fold long lines", |
BOOL|REPAINT, OPT_OFF, &chopline, NULL, |
"Chop long lines", |
{ |
NULL |
"Fold long lines", |
|
"Chop long lines", |
|
NULL |
|
} |
}, |
}, |
#if TAGS |
#if TAGS |
{ 't', STRING|NO_QUERY, 0, NULL, opt_t, |
{ 't', &t_optname, |
"tag: ", NULL, NULL |
STRING|NO_QUERY, 0, NULL, opt_t, |
|
{ "tag: ", NULL, NULL } |
}, |
}, |
{ 'T', STRING, 0, NULL, opt__T, |
{ 'T', &T__optname, |
"tags file: ", NULL, NULL |
STRING, 0, NULL, opt__T, |
|
{ "tags file: ", NULL, NULL } |
}, |
}, |
#endif |
#endif |
{ 'u', TRIPLE|REPAINT, OPT_OFF, &bs_mode, NULL, |
{ 'u', &u_optname, |
"Display underlined text in underline mode", |
TRIPLE|REPAINT, OPT_OFF, &bs_mode, NULL, |
"Backspaces cause overstrike", |
{ |
"Print backspace as ^H" |
"Display underlined text in underline mode", |
|
"Backspaces cause overstrike", |
|
"Print backspace as ^H" |
|
} |
}, |
}, |
{ 'V', NOVAR, 0, NULL, opt__V, |
{ 'V', &V__optname, |
NULL, NULL, NULL |
NOVAR, 0, NULL, opt__V, |
|
{ NULL, NULL, NULL } |
}, |
}, |
{ 'w', BOOL|REPAINT, OPT_ON, &twiddle, NULL, |
{ 'w', &w_optname, |
"Display nothing for lines after end-of-file", |
TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL, |
"Display ~ for lines after end-of-file", |
{ |
NULL |
"Don't highlight first unread line", |
|
"Highlight first unread line after forward-screen", |
|
"Highlight first unread line after any forward movement", |
|
} |
}, |
}, |
{ 'x', NUMBER|REPAINT, 8, &tabstop, NULL, |
{ 'x', &x_optname, |
"Tab stops: ", |
STRING|REPAINT, 0, NULL, opt_x, |
"Tab stops every %d spaces", |
{ |
NULL |
"Tab stops: ", |
|
"0123456789,", |
|
NULL |
|
} |
}, |
}, |
{ 'X', BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL, |
{ 'X', &X__optname, |
"Send init/deinit strings to terminal", |
BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL, |
"Don't use init/deinit strings", |
{ |
NULL |
"Send init/deinit strings to terminal", |
|
"Don't use init/deinit strings", |
|
NULL |
|
} |
}, |
}, |
{ 'y', NUMBER, -1, &forw_scroll, NULL, |
{ 'y', &y_optname, |
"Forward scroll limit: ", |
NUMBER, -1, &forw_scroll, NULL, |
"Forward scroll limit is %d lines", |
{ |
NULL |
"Forward scroll limit: ", |
|
"Forward scroll limit is %d lines", |
|
NULL |
|
} |
}, |
}, |
{ 'z', NUMBER, -1, &swindow, NULL, |
{ 'z', &z_optname, |
"Scroll window size: ", |
NUMBER, -1, &swindow, NULL, |
"Scroll window size is %d lines", |
{ |
NULL |
"Scroll window size: ", |
|
"Scroll window size is %d lines", |
|
NULL |
|
} |
}, |
}, |
{ '?', NOVAR, 0, NULL, opt_query, |
{ '"', "e_optname, |
NULL, NULL, NULL |
STRING, 0, NULL, opt_quote, |
|
{ "quotes: ", NULL, NULL } |
}, |
}, |
{ '\0' } |
{ '~', &tilde_optname, |
|
BOOL|REPAINT, OPT_ON, &twiddle, NULL, |
|
{ |
|
"Don't show tildes after end of file", |
|
"Show tildes after end of file", |
|
NULL |
|
} |
|
}, |
|
{ '?', &query_optname, |
|
NOVAR, 0, NULL, opt_query, |
|
{ NULL, NULL, NULL } |
|
}, |
|
{ '#', £_optname, |
|
NUMBER, 0, &shift_count, NULL, |
|
{ |
|
"Horizontal shift: ", |
|
"Horizontal shift %d positions", |
|
NULL |
|
} |
|
}, |
|
{ '.', &keypad_optname, |
|
BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL, |
|
{ |
|
"Use keypad mode", |
|
"Don't use keypad mode", |
|
NULL |
|
} |
|
}, |
|
{ '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } } |
}; |
}; |
|
|
|
|
|
|
public void |
public void |
init_option() |
init_option() |
{ |
{ |
register struct option *o; |
register struct loption *o; |
|
|
for (o = option; o->oletter != '\0'; o++) |
for (o = option; o->oletter != '\0'; o++) |
{ |
{ |
|
|
*/ |
*/ |
if (o->ovar != NULL) |
if (o->ovar != NULL) |
*(o->ovar) = o->odefault; |
*(o->ovar) = o->odefault; |
|
if (o->otype & INIT_HANDLER) |
|
(*(o->ofunc))(INIT, (char *) NULL); |
} |
} |
} |
} |
|
|
/* |
/* |
* Find an option in the option table. |
* Find an option in the option table, given its option letter. |
*/ |
*/ |
public struct option * |
public struct loption * |
findopt(c) |
findopt(c) |
int c; |
int c; |
{ |
{ |
register struct option *o; |
register struct loption *o; |
|
|
for (o = option; o->oletter != '\0'; o++) |
for (o = option; o->oletter != '\0'; o++) |
{ |
{ |
|
|
return (o); |
return (o); |
} |
} |
return (NULL); |
return (NULL); |
|
} |
|
|
|
/* |
|
* |
|
*/ |
|
static int |
|
is_optchar(c) |
|
char c; |
|
{ |
|
if (SIMPLE_IS_UPPER(c)) |
|
return 1; |
|
if (SIMPLE_IS_LOWER(c)) |
|
return 1; |
|
if (c == '-') |
|
return 1; |
|
return 0; |
|
} |
|
|
|
/* |
|
* Find an option in the option table, given its option name. |
|
* p_optname is the (possibly partial) name to look for, and |
|
* is updated to point after the matched name. |
|
* p_oname if non-NULL is set to point to the full option name. |
|
*/ |
|
public struct loption * |
|
findopt_name(p_optname, p_oname, p_err) |
|
char **p_optname; |
|
char **p_oname; |
|
int *p_err; |
|
{ |
|
char *optname = *p_optname; |
|
register struct loption *o; |
|
register struct optname *oname; |
|
register int len; |
|
int uppercase; |
|
struct loption *maxo = NULL; |
|
struct optname *maxoname = NULL; |
|
int maxlen = 0; |
|
int ambig = 0; |
|
int exact = 0; |
|
char *eq; |
|
|
|
/* |
|
* Check all options. |
|
*/ |
|
for (o = option; o->oletter != '\0'; o++) |
|
{ |
|
/* |
|
* Check all names for this option. |
|
*/ |
|
for (oname = o->onames; oname != NULL; oname = oname->onext) |
|
{ |
|
/* |
|
* Try normal match first (uppercase == 0), |
|
* then, then if it's a TRIPLE option, |
|
* try uppercase match (uppercase == 1). |
|
*/ |
|
for (uppercase = 0; uppercase <= 1; uppercase++) |
|
{ |
|
len = sprefix(optname, oname->oname, uppercase); |
|
if (len <= 0 || is_optchar(optname[len])) |
|
{ |
|
/* |
|
* We didn't use all of the option name. |
|
*/ |
|
continue; |
|
} |
|
if (!exact && len == maxlen) |
|
/* |
|
* Already had a partial match, |
|
* and now there's another one that |
|
* matches the same length. |
|
*/ |
|
ambig = 1; |
|
else if (len > maxlen) |
|
{ |
|
/* |
|
* Found a better match than |
|
* the one we had. |
|
*/ |
|
maxo = o; |
|
maxoname = oname; |
|
maxlen = len; |
|
ambig = 0; |
|
exact = (len == (int)strlen(oname->oname)); |
|
} |
|
if (!(o->otype & TRIPLE)) |
|
break; |
|
} |
|
} |
|
} |
|
if (ambig) |
|
{ |
|
/* |
|
* Name matched more than one option. |
|
*/ |
|
if (p_err != NULL) |
|
*p_err = OPT_AMBIG; |
|
return (NULL); |
|
} |
|
*p_optname = optname + maxlen; |
|
if (p_oname != NULL) |
|
*p_oname = maxoname == NULL ? NULL : maxoname->oname; |
|
return (maxo); |
} |
} |