|
|
1.1 ! root 1: /* ! 2: * Process command line options. ! 3: * Each option is a single letter which controls a program variable. ! 4: * The options have defaults which may be changed via ! 5: * the command line option, or toggled via the "-" command. ! 6: */ ! 7: ! 8: #include "less.h" ! 9: ! 10: #define toupper(c) ((c)-'a'+'A') ! 11: ! 12: /* ! 13: * Types of options. ! 14: */ ! 15: #define BOOL 01 /* Boolean option: 0 or 1 */ ! 16: #define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */ ! 17: #define NUMBER 04 /* Numeric option */ ! 18: #define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */ ! 19: ! 20: /* ! 21: * Variables controlled by command line options. ! 22: */ ! 23: public int p_nbufs, f_nbufs; /* Number of buffers. There are two values, ! 24: one used for input from a pipe and ! 25: the other for input from a file. */ ! 26: public int clean_data; /* Can we assume the data is "clean"? ! 27: (That is, free of nulls, etc) */ ! 28: public int quiet; /* Should we suppress the audible bell? */ ! 29: public int top_search; /* Should forward searches start at the top ! 30: of the screen? (alternative is bottom) */ ! 31: public int top_scroll; /* Repaint screen from top? ! 32: (alternative is scroll from bottom) */ ! 33: public int pr_type; /* Type of prompt (short, medium, long) */ ! 34: public int bs_mode; /* How to process backspaces */ ! 35: public int know_dumb; /* Don't complain about dumb terminals */ ! 36: public int quit_at_eof; /* Quit after hitting end of file twice */ ! 37: public int squeeze; /* Squeeze multiple blank lines into one */ ! 38: public int tabstop; /* Tab settings */ ! 39: public int back_scroll; /* Repaint screen on backwards movement */ ! 40: public int twiddle; /* Display "~" for lines after EOF */ ! 41: ! 42: extern int nbufs; ! 43: extern char *first_cmd; ! 44: extern char *every_first_cmd; ! 45: ! 46: #define DEF_F_NBUFS 5 /* Default for f_nbufs */ ! 47: #define DEF_P_NBUFS 12 /* Default for p_nbufs */ ! 48: ! 49: static struct option ! 50: { ! 51: char oletter; /* The controlling letter (a-z) */ ! 52: char otype; /* Type of the option */ ! 53: int odefault; /* Default value */ ! 54: int *ovar; /* Pointer to the associated variable */ ! 55: char *odesc[3]; /* Description of each value */ ! 56: } option[] = ! 57: { ! 58: { 'c', BOOL, 0, &clean_data, ! 59: { "Don't assume data is clean", ! 60: "Assume data is clean", ! 61: NULL ! 62: } ! 63: }, ! 64: { 'd', BOOL|NO_TOGGLE, 0, &know_dumb, ! 65: { NULL, NULL, NULL} ! 66: }, ! 67: { 'e', BOOL, 0, &quit_at_eof, ! 68: { "Don't quit at end-of-file", ! 69: "Quit at end-of-file", ! 70: NULL ! 71: } ! 72: }, ! 73: { 'h', NUMBER, -1, &back_scroll, ! 74: { "Backwards scroll limit is %d lines", ! 75: NULL, NULL ! 76: } ! 77: }, ! 78: { 'p', BOOL, 0, &top_scroll, ! 79: { "Repaint by scrolling from bottom of screen", ! 80: "Repaint by painting from top of screen", ! 81: NULL ! 82: } ! 83: }, ! 84: { 'x', NUMBER, 8, &tabstop, ! 85: { "Tab stops every %d spaces", ! 86: NULL, NULL ! 87: } ! 88: }, ! 89: { 's', BOOL, 0, &squeeze, ! 90: { "Don't squeeze multiple blank lines", ! 91: "Squeeze multiple blank lines", ! 92: NULL ! 93: } ! 94: }, ! 95: { 't', BOOL, 1, &top_search, ! 96: { "Forward search starts from bottom of screen", ! 97: "Forward search starts from top of screen", ! 98: NULL ! 99: } ! 100: }, ! 101: { 'w', BOOL, 1, &twiddle, ! 102: { "Display nothing for lines after end-of-file", ! 103: "Display ~ for lines after end-of-file", ! 104: NULL ! 105: } ! 106: }, ! 107: { 'm', TRIPLE, 0, &pr_type, ! 108: { "Prompt with a colon", ! 109: "Prompt with a message", ! 110: "Prompt with a verbose message" ! 111: } ! 112: }, ! 113: { 'q', TRIPLE, 0, &quiet, ! 114: { "Ring the bell for errors AND at eof/bof", ! 115: "Ring the bell for errors but not at eof/bof", ! 116: "Never ring the bell" ! 117: } ! 118: }, ! 119: { 'u', TRIPLE, 0, &bs_mode, ! 120: { "Underlined text displayed in underline mode", ! 121: "All backspaces cause overstrike", ! 122: "Backspaces print as ^H" ! 123: } ! 124: }, ! 125: { '\0' } ! 126: }; ! 127: ! 128: public char all_options[64]; /* List of all valid options */ ! 129: ! 130: /* ! 131: * Initialize each option to its default value. ! 132: */ ! 133: public void ! 134: init_option() ! 135: { ! 136: register struct option *o; ! 137: register char *p; ! 138: ! 139: /* ! 140: * First do special cases, not in option table. ! 141: */ ! 142: first_cmd = every_first_cmd = NULL; ! 143: f_nbufs = DEF_F_NBUFS; /* -bf */ ! 144: p_nbufs = DEF_P_NBUFS; /* -bp */ ! 145: ! 146: p = all_options; ! 147: *p++ = 'b'; ! 148: ! 149: for (o = option; o->oletter != '\0'; o++) ! 150: { ! 151: /* ! 152: * Set each variable to its default. ! 153: * Also make a list of all options, in "all_options". ! 154: */ ! 155: *(o->ovar) = o->odefault; ! 156: *p++ = o->oletter; ! 157: if (o->otype & TRIPLE) ! 158: *p++ = toupper(o->oletter); ! 159: } ! 160: *p = '\0'; ! 161: } ! 162: ! 163: /* ! 164: * Toggle command line flags from within the program. ! 165: * Used by the "-" command. ! 166: */ ! 167: public void ! 168: toggle_option(c) ! 169: int c; ! 170: { ! 171: register struct option *o; ! 172: char message[100]; ! 173: char buf[5]; ! 174: ! 175: /* ! 176: * First check for special cases not handled by the option table. ! 177: */ ! 178: switch (c) ! 179: { ! 180: case 'b': ! 181: sprintf(message, "%d buffers", nbufs); ! 182: error(message); ! 183: return; ! 184: } ! 185: ! 186: ! 187: for (o = option; o->oletter != '\0'; o++) ! 188: { ! 189: if ((o->otype & BOOL) && (o->oletter == c) && ! 190: (o->otype & NO_TOGGLE) == 0) ! 191: { ! 192: /* ! 193: * Boolean option: ! 194: * just toggle it. ! 195: */ ! 196: *(o->ovar) = ! *(o->ovar); ! 197: error(o->odesc[*(o->ovar)]); ! 198: return; ! 199: } else if ((o->otype & TRIPLE) && (o->oletter == c) && ! 200: (o->otype & NO_TOGGLE) == 0) ! 201: { ! 202: /* ! 203: * Triple-valued option with lower case letter: ! 204: * make it 1 unless already 1, then make it 0. ! 205: */ ! 206: *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1; ! 207: error(o->odesc[*(o->ovar)]); ! 208: return; ! 209: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c) && ! 210: (o->otype & NO_TOGGLE) == 0) ! 211: { ! 212: /* ! 213: * Triple-valued option with upper case letter: ! 214: * make it 2 unless already 2, then make it 0. ! 215: */ ! 216: *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2; ! 217: error(o->odesc[*(o->ovar)]); ! 218: return; ! 219: } else if ((o->otype & NUMBER) && (o->oletter == c) && ! 220: (o->otype & NO_TOGGLE) == 0) ! 221: { ! 222: sprintf(message, o->odesc[0], *(o->ovar)); ! 223: error(message); ! 224: return; ! 225: } ! 226: } ! 227: ! 228: if (control_char(c)) ! 229: sprintf(buf, "^%c", carat_char(c)); ! 230: else ! 231: sprintf(buf, "%c", c); ! 232: sprintf(message, "\"-%s\": no such flag. Use one of \"%s\"", ! 233: buf, all_options); ! 234: error(message); ! 235: } ! 236: ! 237: /* ! 238: * Scan an argument (either from command line or from LESS environment ! 239: * variable) and process it. ! 240: */ ! 241: public void ! 242: scan_option(s) ! 243: char *s; ! 244: { ! 245: register struct option *o; ! 246: register int c; ! 247: ! 248: if (s == NULL) ! 249: return; ! 250: ! 251: next: ! 252: if (*s == '\0') ! 253: return; ! 254: switch (c = *s++) ! 255: { ! 256: case '-': ! 257: case ' ': ! 258: case '\t': ! 259: goto next; ! 260: case '+': ! 261: if (*s == '+') ! 262: every_first_cmd = ++s; ! 263: first_cmd = s; ! 264: return; ! 265: case 'b': ! 266: switch (*s) ! 267: { ! 268: case 'f': ! 269: s++; ! 270: f_nbufs = getnum(&s, 'b'); ! 271: break; ! 272: case 'p': ! 273: s++; ! 274: p_nbufs = getnum(&s, 'b'); ! 275: break; ! 276: default: ! 277: f_nbufs = p_nbufs = getnum(&s, 'b'); ! 278: break; ! 279: } ! 280: goto next; ! 281: } ! 282: ! 283: for (o = option; o->oletter != '\0'; o++) ! 284: { ! 285: if ((o->otype & BOOL) && (o->oletter == c)) ! 286: { ! 287: *(o->ovar) = ! o->odefault; ! 288: goto next; ! 289: } else if ((o->otype & TRIPLE) && (o->oletter == c)) ! 290: { ! 291: *(o->ovar) = (o->odefault == 1) ? 0 : 1; ! 292: goto next; ! 293: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c)) ! 294: { ! 295: *(o->ovar) = (o->odefault == 2) ? 0 : 2; ! 296: goto next; ! 297: } else if ((o->otype & NUMBER) && (o->oletter == c)) ! 298: { ! 299: *(o->ovar) = getnum(&s, c); ! 300: goto next; ! 301: } ! 302: } ! 303: ! 304: printf("\"-%c\": invalid flag\n", c); ! 305: exit(1); ! 306: } ! 307: ! 308: /* ! 309: * Translate a string into a number. ! 310: * Like atoi(), but takes a pointer to a char *, and updates ! 311: * the char * to point after the translated number. ! 312: */ ! 313: static int ! 314: getnum(sp, c) ! 315: char **sp; ! 316: int c; ! 317: { ! 318: register char *s; ! 319: register int n; ! 320: ! 321: s = *sp; ! 322: if (*s < '0' || *s > '9') ! 323: { ! 324: printf("number is required after -%c\n", c); ! 325: exit(1); ! 326: } ! 327: ! 328: n = 0; ! 329: while (*s >= '0' && *s <= '9') ! 330: n = 10 * n + *s++ - '0'; ! 331: *sp = s; ! 332: return (n); ! 333: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.