This is option.c in view mode; [Download] [Up]
/* * 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, or toggled via the "-" command. */ #include "less.h" #define toupper(c) ((c)-'a'+'A') #define END_OPTION_STRING ('$') /* * Types of options. */ #define BOOL 01 /* Boolean option: 0 or 1 */ #define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */ #define NUMBER 04 /* Numeric option */ #define REPAINT 040 /* Repaint screen after toggling option */ #define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */ /* * Variables controlled by command line options. */ public int clean_data; /* Can we assume the data is "clean"? (That is, free of nulls, etc) */ public int quiet; /* Should we suppress the audible bell? */ public int how_search; /* Where should forward searches start? */ public int top_scroll; /* Repaint screen from top? (alternative is scroll from bottom) */ public int pr_type; /* Type of prompt (short, medium, long) */ public int bs_mode; /* How to process backspaces */ public int know_dumb; /* Don't complain about dumb terminals */ public int quit_at_eof; /* Quit after hitting end of file twice */ public int squeeze; /* Squeeze multiple blank lines into one */ public int tabstop; /* Tab settings */ public int back_scroll; /* Repaint screen on backwards movement */ public int twiddle; /* Display "~" for lines after EOF */ public int caseless; /* Do "caseless" searches */ public int linenums; /* Use line numbers */ public int cbufs; /* Current number of buffers */ public int autobuf; public int plusoption; extern char *prproto[]; extern char *eqproto; extern int nbufs; extern int sc_window; extern int ispipe; extern char *first_cmd; extern char *every_first_cmd; #if LOGFILE extern char *namelogfile; extern int force_logfile; extern int logfile; #endif #if TAGS extern char *tagfile; extern char *tagpattern; public int tagoption = 0; #endif static char *opt_P(); static struct option { char oletter; /* The controlling letter (a-z) */ char otype; /* Type of the option */ int odefault; /* Default value */ int *ovar; /* Pointer to the associated variable */ char *odesc[3]; /* Description of each value */ } option[] = { { 'a', TRIPLE, 0, &how_search, { "Forward search starts at second REAL line displayed", "Forward search starts at bottom of screen", "Forward search starts at second SCREEN line displayed" } }, { 'b', NUMBER, 10, &cbufs, { "%d buffers", NULL, NULL } }, { 'B', BOOL, 1, &autobuf, { "Don't automatically allocate buffers", "Automatically allocate buffers when needed", NULL } }, { 'c', TRIPLE, 0, &top_scroll, { "Repaint by scrolling from bottom of screen", "Repaint by clearing each line", "Repaint by painting from top of screen" } }, { 'd', BOOL|NO_TOGGLE, 0, &know_dumb, { NULL, NULL, NULL} }, { 'e', TRIPLE, 0, &quit_at_eof, { "Don't quit at end-of-file", "Quit at end-of-file", "Quit immediately at end-of-file" } }, { 'h', NUMBER, -1, &back_scroll, { "Backwards scroll limit is %d lines", NULL, NULL } }, { 'i', BOOL, 0, &caseless, { "Case is significant in searches", "Ignore case in searches", NULL } }, { 'm', TRIPLE, 0, &pr_type, { "Short prompt", "Medium prompt", "Long prompt" } }, { 'n', BOOL, 1, &linenums, { "Don't use line numbers", "Use line numbers", NULL } }, { 'q', TRIPLE, 0, &quiet, { "Ring the bell for errors AND at eof/bof", "Ring the bell for errors but not at eof/bof", "Never ring the bell" } }, { 's', BOOL|REPAINT, 0, &squeeze, { "Don't squeeze multiple blank lines", "Squeeze multiple blank lines", NULL } }, { 'u', TRIPLE|REPAINT, 0, &bs_mode, { "Underlined text displayed in underline mode", "Backspaces cause overstrike", "Backspaces print as ^H" } }, { 'w', BOOL|REPAINT, 1, &twiddle, { "Display nothing for lines after end-of-file", "Display ~ for lines after end-of-file", NULL } }, { 'x', NUMBER|REPAINT, 8, &tabstop, { "Tab stops every %d spaces", NULL, NULL } }, { 'z', NUMBER|REPAINT, -1, &sc_window, { "Scroll window size is %d lines", NULL, NULL } }, { '\0' } }; /* * Initialize each option to its default value. */ public void init_option() { register struct option *o; first_cmd = every_first_cmd = NULL; for (o = option; o->oletter != '\0'; o++) { /* * Set each variable to its default. */ *(o->ovar) = o->odefault; } } /* * Toggle command line flags from within the program. * Used by the "-" and "_" commands. * If do_toggle is zero, just report the current setting, without changing it. */ public void toggle_option(s, do_toggle) char *s; int do_toggle; { int c; register struct option *o; char *msg; int n; int dorepaint; char message[100]; c = *s++; switch (c) { case 'P': /* * Special case for -P. */ if (*s == '\0') error(prproto[pr_type]); else (void) opt_P(s); return; #if TAGS case 't': /* * Special case for -t. */ if (*s == '\0') { error("no tag"); return; } findtag(s); if (tagfile != NULL) { edit(tagfile); (void) tagsearch(); } return; #endif #if LOGFILE case 'L': /* * Special case for -l and -L. */ force_logfile = 1; goto case_l; case 'l': force_logfile = 0; case_l: if (*s == '\0') { if (logfile < 0) error("no log file"); else { sprintf(message, "log file \"%s\"", namelogfile); error(message); } return; } if (!ispipe) { error("input is not a pipe"); return; } if (logfile >= 0) { error("log file is already in use"); return; } namelogfile = save(s); use_logfile(); sync_logfile(); return; #endif } msg = NULL; for (o = option; o->oletter != '\0'; o++) { if (o->otype & NO_TOGGLE) continue; dorepaint = (o->otype & REPAINT); if ((o->otype & BOOL) && (o->oletter == c)) { /* * Boolean option: * just toggle it. */ if (do_toggle) *(o->ovar) = ! *(o->ovar); } else if ((o->otype & TRIPLE) && (o->oletter == c)) { /* * Triple-valued option with lower case letter: * make it 1 unless already 1, then make it 0. */ if (do_toggle) *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1; } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c)) { /* * Triple-valued option with upper case letter: * make it 2 unless already 2, then make it 0. */ if (do_toggle) *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2; } else if ((o->otype & NUMBER) && (o->oletter == c)) { n = getnum(&s, '\0'); if (n < 0) { /* * No number; just a query. * No need to repaint screen. */ dorepaint = 0; } else { /* * Number follows the option letter. * Set the variable to that number. */ if (do_toggle) *(o->ovar) = n; } /* * Special case for -b. * Call ch_init to set new number of buffers. */ if (o->ovar == &cbufs) ch_init(cbufs, 1); sprintf(message, o->odesc[0], (o->ovar == &back_scroll) ? get_back_scroll() : *(o->ovar)); msg = message; } else continue; /* * Print a message describing the new setting. */ if (msg == NULL) msg = o->odesc[*(o->ovar)]; error(msg); if (do_toggle && dorepaint) repaint(); return; } if (control_char(c)) sprintf(message, "-^%c", carat_char(c)); else sprintf(message, "-%c", c); strcat(message, ": no such flag."); error(message); } /* * Determine if an option is a single character option (BOOL or TRIPLE), * or if it a multi-character option (NUMBER). */ public int single_char_option(c) int c; { register struct option *o; if (c == 'P') return (0); #if TAGS if (c == 't') return (0); #endif #if LOGFILE if (c == 'l' || c == 'L') return (0); #endif for (o = option; o->oletter != '\0'; o++) if (o->oletter == c) return (o->otype & (BOOL|TRIPLE)); return (1); } /* * 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; char message[80]; if (*s == '\0') { sprintf(message, "string is required after -%c", c); error(message); exit(1); } for (p = s; *p != '\0'; p++) if (*p == END_OPTION_STRING) { *p = '\0'; return (p+1); } return (p); } /* * Scan an argument (either from command line or from LESS environment * variable) and process it. */ public void scan_option(s) char *s; { register struct option *o; register int c; int set_default; char message[80]; if (s == NULL) return; set_default = 0; next: if (*s == '\0') return; switch (c = *s++) { case ' ': case '\t': case END_OPTION_STRING: goto next; case '-': if (set_default = (*s == '+')) s++; goto next; case '+': plusoption = 1; if (*s == '+') every_first_cmd = save(++s); first_cmd = s; s = optstring(s, c); goto next; #if LOGFILE case 'L': force_logfile = 1; /* FALLTHRU */ case 'l': namelogfile = s; s = optstring(s, c); goto next; #endif #if TAGS case 't': { char *p; tagoption = 1; p = s; s = optstring(s, c); findtag(p); goto next; } #endif case 'P': s = opt_P(s); goto next; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* * Handle special "more" compatibility form "-number" * (instead of -znumber) to set the scrolling window size. */ s--; c = 'z'; break; } for (o = option; o->oletter != '\0'; o++) { if ((o->otype & BOOL) && (o->oletter == c)) { if (set_default) *(o->ovar) = o->odefault; else *(o->ovar) = ! o->odefault; goto next; } else if ((o->otype & TRIPLE) && (o->oletter == c)) { if (set_default) *(o->ovar) = o->odefault; else *(o->ovar) = (o->odefault == 1) ? 0 : 1; goto next; } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c)) { if (set_default) *(o->ovar) = o->odefault; else *(o->ovar) = (o->odefault == 2) ? 0 : 2; goto next; } else if ((o->otype & NUMBER) && (o->oletter == c)) { *(o->ovar) = getnum(&s, c); goto next; } } sprintf(message, "\"-%c\": invalid flag", c); error(message); exit(1); } /* * Special case for -P. */ static char * opt_P(s) register char *s; { register char *es; register char **proto; es = optstring(s, 'P'); /* * Figure out which prototype string should be changed. */ switch (*s) { case 'm': proto = &prproto[PR_MEDIUM]; s++; break; case 'M': proto = &prproto[PR_LONG]; s++; break; case '=': proto = &eqproto; s++; break; default: proto = &prproto[pr_type]; break; } free(*proto); *proto = save(s); return (es); } /* * 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 int getnum(sp, c) char **sp; int c; { register char *s; register int n; char message[80]; s = *sp; if (*s < '0' || *s > '9') { if (c == '\0') return (-1); sprintf(message, "number is required after -%c", c); error(message); exit(1); } n = 0; while (*s >= '0' && *s <= '9') n = 10 * n + *s++ - '0'; *sp = s; return (n); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.